Merge "Add test with static wallpaper for switchUser"
diff --git a/Android.bp b/Android.bp
index 2a6afe5..cfab18e 100644
--- a/Android.bp
+++ b/Android.bp
@@ -694,3 +694,12 @@
"ProtoLibraries.bp",
"TestProtoLibraries.bp",
]
+
+java_api_contribution {
+ name: "api-stubs-docs-non-updatable-public-stubs",
+ api_surface: "public",
+ api_file: "core/api/current.txt",
+ visibility: [
+ "//build/orchestrator/apis",
+ ],
+}
diff --git a/StubLibraries.bp b/StubLibraries.bp
index 48c44c9..fc046fb 100644
--- a/StubLibraries.bp
+++ b/StubLibraries.bp
@@ -598,3 +598,12 @@
],
visibility: ["//visibility:public"],
}
+
+java_api_contribution {
+ name: "frameworks-base-core-api-module-lib-stubs",
+ api_surface: "module-lib",
+ api_file: "core/api/module-lib-current.txt",
+ visibility: [
+ "//build/orchestrator/apis",
+ ],
+}
diff --git a/apct-tests/perftests/core/src/android/input/MotionPredictorBenchmark.kt b/apct-tests/perftests/core/src/android/input/MotionPredictorBenchmark.kt
new file mode 100644
index 0000000..3d447ac
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/input/MotionPredictorBenchmark.kt
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package android.input
+
+import android.content.Context
+import android.content.res.Resources
+import android.os.SystemProperties
+import android.perftests.utils.PerfStatusReporter
+import android.view.InputDevice
+import android.view.MotionEvent
+import android.view.MotionEvent.ACTION_DOWN
+import android.view.MotionEvent.ACTION_MOVE
+import android.view.MotionEvent.PointerCoords
+import android.view.MotionEvent.PointerProperties
+import android.view.MotionPredictor
+
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.filters.LargeTest
+import androidx.test.ext.junit.runners.AndroidJUnit4
+
+import org.junit.After
+import org.junit.Assert.assertEquals
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.`when`
+
+import java.time.Duration
+
+private fun getStylusMotionEvent(
+ eventTime: Duration,
+ action: Int,
+ x: Float,
+ y: Float,
+ ): MotionEvent{
+ val pointerCount = 1
+ val properties = arrayOfNulls<MotionEvent.PointerProperties>(pointerCount)
+ val coords = arrayOfNulls<MotionEvent.PointerCoords>(pointerCount)
+
+ for (i in 0 until pointerCount) {
+ properties[i] = PointerProperties()
+ properties[i]!!.id = i
+ properties[i]!!.toolType = MotionEvent.TOOL_TYPE_STYLUS
+ coords[i] = PointerCoords()
+ coords[i]!!.x = x
+ coords[i]!!.y = y
+ }
+
+ return MotionEvent.obtain(/*downTime=*/0, eventTime.toMillis(), action, properties.size,
+ properties, coords, /*metaState=*/0, /*buttonState=*/0,
+ /*xPrecision=*/0f, /*yPrecision=*/0f, /*deviceId=*/0, /*edgeFlags=*/0,
+ InputDevice.SOURCE_STYLUS, /*flags=*/0)
+}
+
+private fun getPredictionContext(offset: Duration, enablePrediction: Boolean): Context {
+ val context = mock(Context::class.java)
+ val resources: Resources = mock(Resources::class.java)
+ `when`(context.getResources()).thenReturn(resources)
+ `when`(resources.getInteger(
+ com.android.internal.R.integer.config_motionPredictionOffsetNanos)).thenReturn(
+ offset.toNanos().toInt())
+ `when`(resources.getBoolean(
+ com.android.internal.R.bool.config_enableMotionPrediction)).thenReturn(enablePrediction)
+ return context
+}
+
+@RunWith(AndroidJUnit4::class)
+@LargeTest
+class MotionPredictorBenchmark {
+ private val instrumentation = InstrumentationRegistry.getInstrumentation()
+ @get:Rule
+ val perfStatusReporter = PerfStatusReporter()
+ private val initialPropertyValue =
+ SystemProperties.get("persist.input.enable_motion_prediction")
+
+ private var eventTime = Duration.ofMillis(1)
+
+ @Before
+ fun setUp() {
+ instrumentation.uiAutomation.executeShellCommand(
+ "setprop persist.input.enable_motion_prediction true")
+ }
+
+ @After
+ fun tearDown() {
+ instrumentation.uiAutomation.executeShellCommand(
+ "setprop persist.input.enable_motion_prediction $initialPropertyValue")
+ }
+
+ /**
+ * In a typical usage, app will send the event to the predictor and then call .predict to draw
+ * a prediction. In a loop, we keep sending MOVE and then calling .predict to simulate this.
+ */
+ @Test
+ fun timeRecordAndPredict() {
+ val offset = Duration.ofMillis(1)
+ val predictor = MotionPredictor(getPredictionContext(offset, /*enablePrediction=*/true))
+ // ACTION_DOWN t=0 x=0 y=0
+ predictor.record(getStylusMotionEvent(eventTime, ACTION_DOWN, /*x=*/0f, /*y=*/0f))
+
+ val state = perfStatusReporter.getBenchmarkState()
+ while (state.keepRunning()) {
+ eventTime += Duration.ofMillis(1)
+
+ // Send MOVE event and then call .predict
+ val moveEvent = getStylusMotionEvent(eventTime, ACTION_MOVE, /*x=*/1f, /*y=*/2f)
+ predictor.record(moveEvent)
+ val predictionTime = eventTime + Duration.ofMillis(2)
+ val predicted = predictor.predict(predictionTime.toNanos())
+ assertEquals(1, predicted.size)
+ assertEquals((predictionTime + offset).toMillis(), predicted[0].eventTime)
+ }
+ }
+
+ /**
+ * The creation of the predictor should happen infrequently. However, we still want to be
+ * mindful of the load times.
+ */
+ @Test
+ fun timeCreatePredictor() {
+ val context = getPredictionContext(
+ /*offset=*/Duration.ofMillis(1), /*enablePrediction=*/true)
+
+ val state = perfStatusReporter.getBenchmarkState()
+ while (state.keepRunning()) {
+ MotionPredictor(context)
+ }
+ }
+}
diff --git a/apct-tests/perftests/core/src/android/input/OWNERS b/apct-tests/perftests/core/src/android/input/OWNERS
new file mode 100644
index 0000000..95e3f02
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/input/OWNERS
@@ -0,0 +1,3 @@
+include platform/frameworks/base:/INPUT_OWNERS
+
+# Bug component: 136048
diff --git a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
index 9257469..64ba6d1 100644
--- a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
+++ b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
@@ -250,24 +250,27 @@
/**
* Tests starting an uninitialized user, with wait times in between iterations.
- * Measures the time until ACTION_USER_STARTED is received.
+ * Measures the time until the ProgressListener callback.
*/
@Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
public void startUser_realistic() throws RemoteException {
while (mRunner.keepRunning()) {
mRunner.pauseTiming();
final int userId = createUserNoFlags();
+ final ProgressWaiter waiter = new ProgressWaiter();
waitForBroadcastIdle();
- runThenWaitForBroadcasts(userId, () -> {
- mRunner.resumeTiming();
- Log.i(TAG, "Starting timer");
+ mRunner.resumeTiming();
+ Log.i(TAG, "Starting timer");
- mIam.startUserInBackground(userId);
- }, Intent.ACTION_USER_STARTED);
+ final boolean success = mIam.startUserInBackgroundWithListener(userId, waiter)
+ && waiter.waitForFinish(TIMEOUT_IN_SECOND * 1000);
mRunner.pauseTiming();
Log.i(TAG, "Stopping timer");
+
+ assertTrue("Error: could not start user " + userId, success);
+
removeUser(userId);
waitCoolDownPeriod();
mRunner.resumeTimingForNextIteration();
diff --git a/apct-tests/perftests/packagemanager/AndroidManifest.xml b/apct-tests/perftests/packagemanager/AndroidManifest.xml
index 3b9431f..b4a34b8 100644
--- a/apct-tests/perftests/packagemanager/AndroidManifest.xml
+++ b/apct-tests/perftests/packagemanager/AndroidManifest.xml
@@ -26,6 +26,7 @@
<permission android:name="com.android.perftests.packagemanager.TestPermission" />
<uses-permission android:name="com.android.perftests.packagemanager.TestPermission" />
+ <uses-permission android:name="android.permission.GET_APP_METADATA" />
<queries>
<package android:name="com.android.perftests.appenumeration0" />
diff --git a/apct-tests/perftests/packagemanager/src/android/os/PackageManagerPerfTest.java b/apct-tests/perftests/packagemanager/src/android/os/PackageManagerPerfTest.java
index 673c6a3..4bcc8c4 100644
--- a/apct-tests/perftests/packagemanager/src/android/os/PackageManagerPerfTest.java
+++ b/apct-tests/perftests/packagemanager/src/android/os/PackageManagerPerfTest.java
@@ -19,10 +19,15 @@
import static libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
import static libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
+import static org.junit.Assert.assertEquals;
+
+import android.Manifest;
import android.compat.testing.PlatformCompatChangeRule;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentSender;
+import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
import android.perftests.utils.BenchmarkState;
import android.perftests.utils.PerfStatusReporter;
@@ -31,11 +36,19 @@
import androidx.test.filters.LargeTest;
import androidx.test.platform.app.InstrumentationRegistry;
+import com.android.compatibility.common.util.AdoptShellPermissionsRule;
+import com.android.cts.install.lib.Install;
+import com.android.cts.install.lib.InstallUtils;
+import com.android.cts.install.lib.LocalIntentSender;
+import com.android.cts.install.lib.TestApp;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.io.IOException;
+
@RunWith(AndroidJUnit4.class)
@LargeTest
public class PackageManagerPerfTest {
@@ -46,6 +59,8 @@
private static final ComponentName TEST_ACTIVITY =
new ComponentName("com.android.perftests.packagemanager",
"android.perftests.utils.PerfTestActivity");
+ private static final String TEST_FIELD = "test";
+ private static final String TEST_VALUE = "value";
@Rule
public final PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
@@ -53,9 +68,39 @@
@Rule
public final PlatformCompatChangeRule mPlatformCompatChangeRule =
new PlatformCompatChangeRule();
+ @Rule
+ public AdoptShellPermissionsRule mAdoptShellPermissionsRule = new AdoptShellPermissionsRule(
+ InstrumentationRegistry.getInstrumentation().getUiAutomation(),
+ Manifest.permission.INSTALL_PACKAGES,
+ Manifest.permission.DELETE_PACKAGES);
+
+ final Context mContext = InstrumentationRegistry.getInstrumentation().getContext();
+ private PackageInstaller mPackageInstaller;
public PackageManagerPerfTest() throws PackageManager.NameNotFoundException {
- final Context context = InstrumentationRegistry.getInstrumentation().getContext();
+ mPackageInstaller = mContext.getPackageManager().getPackageInstaller();
+ }
+
+ private void installTestApp(TestApp testApp) throws IOException, InterruptedException {
+ Install install = Install.single(testApp);
+ final int expectedSessionId = install.createSession();
+ PackageInstaller.Session session =
+ InstallUtils.openPackageInstallerSession(expectedSessionId);
+ PersistableBundle bundle = new PersistableBundle();
+ bundle.putString(TEST_FIELD, TEST_VALUE);
+ session.setAppMetadata(bundle);
+ LocalIntentSender localIntentSender = new LocalIntentSender();
+ session.commit(localIntentSender.getIntentSender());
+ Intent intent = localIntentSender.getResult();
+ InstallUtils.assertStatusSuccess(intent);
+ }
+
+ private void uninstallTestApp(String packageName) throws InterruptedException {
+ LocalIntentSender localIntentSender = new LocalIntentSender();
+ IntentSender intentSender = localIntentSender.getIntentSender();
+ mPackageInstaller.uninstall(packageName, intentSender);
+ Intent intent = localIntentSender.getResult();
+ InstallUtils.assertStatusSuccess(intent);
}
@Before
@@ -65,6 +110,24 @@
}
@Test
+ public void testGetAppMetadata() throws Exception {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ installTestApp(TestApp.A1);
+ final PackageManager pm =
+ InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageManager();
+ final String packageName = TestApp.A1.getPackageName();
+
+ while (state.keepRunning()) {
+ PersistableBundle bundle = pm.getAppMetadata(packageName);
+ state.pauseTiming();
+ assertEquals(bundle.size(), 1);
+ assertEquals(bundle.getString(TEST_FIELD), TEST_VALUE);
+ state.resumeTiming();
+ }
+ uninstallTestApp(packageName);
+ }
+
+ @Test
@DisableCompatChanges(PackageManager.FILTER_APPLICATION_QUERY)
public void testCheckPermissionExists() {
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/TestPackageInstaller.java b/apct-tests/perftests/utils/src/android/perftests/utils/TestPackageInstaller.java
index 15a65ce..1397706 100644
--- a/apct-tests/perftests/utils/src/android/perftests/utils/TestPackageInstaller.java
+++ b/apct-tests/perftests/utils/src/android/perftests/utils/TestPackageInstaller.java
@@ -133,9 +133,9 @@
mContext.registerReceiver(this, filter,
Context.RECEIVER_EXPORTED_UNAUDITED);
- Intent intent = new Intent(action);
+ Intent intent = new Intent(action).setPackage(mContext.getPackageName());
PendingIntent pending = PendingIntent.getBroadcast(mContext, sessionId, intent,
- PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
return pending.getIntentSender();
}
diff --git a/apex/jobscheduler/framework/java/android/app/job/IJobService.aidl b/apex/jobscheduler/framework/java/android/app/job/IJobService.aidl
index 2bb82bd..f8dc3b0 100644
--- a/apex/jobscheduler/framework/java/android/app/job/IJobService.aidl
+++ b/apex/jobscheduler/framework/java/android/app/job/IJobService.aidl
@@ -32,6 +32,8 @@
/** Stop execution of application's job. */
@UnsupportedAppUsage
void stopJob(in JobParameters jobParams);
+ /** Inform the job of a change in the network it should use. */
+ void onNetworkChanged(in JobParameters jobParams);
/** Update JS of how much data has been downloaded. */
void getTransferredDownloadBytes(in JobParameters jobParams, in JobWorkItem jobWorkItem);
/** Update JS of how much data has been uploaded. */
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobParameters.java b/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
index 18ddffb..4be8766 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
@@ -104,6 +104,12 @@
*/
public static final int INTERNAL_STOP_REASON_USER_UI_STOP =
JobProtoEnums.INTERNAL_STOP_REASON_USER_UI_STOP; // 11.
+ /**
+ * The app didn't respond quickly enough from JobScheduler's perspective.
+ * @hide
+ */
+ public static final int INTERNAL_STOP_REASON_ANR =
+ JobProtoEnums.INTERNAL_STOP_REASON_ANR; // 12.
/**
* All the stop reason codes. This should be regarded as an immutable array at runtime.
@@ -128,6 +134,7 @@
INTERNAL_STOP_REASON_RTC_UPDATED,
INTERNAL_STOP_REASON_SUCCESSFUL_FINISH,
INTERNAL_STOP_REASON_USER_UI_STOP,
+ INTERNAL_STOP_REASON_ANR,
};
/**
@@ -149,6 +156,7 @@
case INTERNAL_STOP_REASON_RTC_UPDATED: return "rtc_updated";
case INTERNAL_STOP_REASON_SUCCESSFUL_FINISH: return "successful_finish";
case INTERNAL_STOP_REASON_USER_UI_STOP: return "user_ui_stop";
+ case INTERNAL_STOP_REASON_ANR: return "anr";
default: return "unknown:" + reasonCode;
}
}
@@ -290,7 +298,8 @@
private final boolean mIsUserInitiated;
private final Uri[] mTriggeredContentUris;
private final String[] mTriggeredContentAuthorities;
- private final Network network;
+ @Nullable
+ private Network mNetwork;
private int mStopReason = STOP_REASON_UNDEFINED;
private int mInternalStopReason = INTERNAL_STOP_REASON_UNKNOWN;
@@ -313,7 +322,7 @@
this.mIsUserInitiated = isUserInitiated;
this.mTriggeredContentUris = triggeredContentUris;
this.mTriggeredContentAuthorities = triggeredContentAuthorities;
- this.network = network;
+ this.mNetwork = network;
this.mJobNamespace = namespace;
}
@@ -330,7 +339,6 @@
* @see JobScheduler#forNamespace(String)
* @return The namespace this job was scheduled in. Will be {@code null} if there was no
* explicit namespace set and this job is therefore in the default namespace.
- * @hide
*/
@Nullable
public String getJobNamespace() {
@@ -478,7 +486,7 @@
* @see JobInfo.Builder#setRequiredNetwork(NetworkRequest)
*/
public @Nullable Network getNetwork() {
- return network;
+ return mNetwork;
}
/**
@@ -573,9 +581,9 @@
mTriggeredContentUris = in.createTypedArray(Uri.CREATOR);
mTriggeredContentAuthorities = in.createStringArray();
if (in.readInt() != 0) {
- network = Network.CREATOR.createFromParcel(in);
+ mNetwork = Network.CREATOR.createFromParcel(in);
} else {
- network = null;
+ mNetwork = null;
}
mStopReason = in.readInt();
mInternalStopReason = in.readInt();
@@ -583,6 +591,11 @@
}
/** @hide */
+ public void setNetwork(@Nullable Network network) {
+ mNetwork = network;
+ }
+
+ /** @hide */
public void setStopReason(@StopReason int reason, int internalStopReason,
String debugStopReason) {
mStopReason = reason;
@@ -614,9 +627,9 @@
dest.writeBoolean(mIsUserInitiated);
dest.writeTypedArray(mTriggeredContentUris, flags);
dest.writeStringArray(mTriggeredContentAuthorities);
- if (network != null) {
+ if (mNetwork != null) {
dest.writeInt(1);
- network.writeToParcel(dest, flags);
+ mNetwork.writeToParcel(dest, flags);
} else {
dest.writeInt(0);
}
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobScheduler.java b/apex/jobscheduler/framework/java/android/app/job/JobScheduler.java
index 33668c7..4aec484 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobScheduler.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobScheduler.java
@@ -271,7 +271,6 @@
* but will instead create or update the job inside the current namespace. A JobScheduler
* instance dedicated to a namespace must be used to schedule or update jobs in that namespace.
* @see #getNamespace()
- * @hide
*/
@NonNull
public JobScheduler forNamespace(@NonNull String namespace) {
@@ -282,7 +281,6 @@
* Get the namespace this JobScheduler instance is operating in. A {@code null} value means
* that the app has not specified a namespace for this instance, and it is therefore using the
* default namespace.
- * @hide
*/
@Nullable
public String getNamespace() {
@@ -395,14 +393,21 @@
public abstract void cancel(int jobId);
/**
- * Cancel <em>all</em> jobs that have been scheduled by the calling application.
+ * Cancel all jobs that have been scheduled in the current namespace by the
+ * calling application.
+ *
+ * <p>
+ * Starting with Android version {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, this
+ * will only cancel within the current namespace. If a namespace hasn't been explicitly set
+ * with {@link #forNamespace(String)}, then this will cancel jobs in the default namespace.
+ * To cancel all jobs scheduled by the application,
+ * use {@link #cancelInAllNamespaces()} instead.
*/
public abstract void cancelAll();
/**
* Cancel <em>all</em> jobs that have been scheduled by the calling application, regardless of
* namespace.
- * @hide
*/
public void cancelInAllNamespaces() {
throw new RuntimeException("Not implemented. Must override in a subclass.");
@@ -424,7 +429,6 @@
* If a namespace hasn't been explicitly set with {@link #forNamespace(String)},
* then this will return jobs in the default namespace.
* This includes jobs that are currently started as well as those that are still waiting to run.
- * @hide
*/
@NonNull
public Map<String, List<JobInfo>> getPendingJobsInAllNamespaces() {
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobService.java b/apex/jobscheduler/framework/java/android/app/job/JobService.java
index 449c316..31d2266 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobService.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobService.java
@@ -27,6 +27,7 @@
import android.compat.Compatibility;
import android.content.Intent;
import android.os.IBinder;
+import android.util.Log;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -131,6 +132,11 @@
return JobService.this.getTransferredUploadBytes(params, item);
}
}
+
+ @Override
+ public void onNetworkChanged(@NonNull JobParameters params) {
+ JobService.this.onNetworkChanged(params);
+ }
};
}
return mEngine.getBinder();
@@ -232,6 +238,27 @@
public abstract boolean onStopJob(JobParameters params);
/**
+ * This method is called that for a job that has a network constraint when the network
+ * to be used by the job changes. The new network object will be available via
+ * {@link JobParameters#getNetwork()}. Any network that results in this method call will
+ * match the job's requested network constraints.
+ *
+ * <p>
+ * For example, if a device is on a metered mobile network and then connects to an
+ * unmetered WiFi network, and the job has indicated that both networks satisfy its
+ * network constraint, then this method will be called to notify the job of the new
+ * unmetered WiFi network.
+ *
+ * @param params The parameters identifying this job, similar to what was supplied to the job in
+ * the {@link #onStartJob(JobParameters)} callback, but with an updated network.
+ * @see JobInfo.Builder#setRequiredNetwork(android.net.NetworkRequest)
+ * @see JobInfo.Builder#setRequiredNetworkType(int)
+ */
+ public void onNetworkChanged(@NonNull JobParameters params) {
+ Log.w(TAG, "onNetworkChanged() not implemented. Must override in a subclass.");
+ }
+
+ /**
* Update the amount of data this job is estimated to transfer after the job has started.
*
* @see JobInfo.Builder#setEstimatedNetworkBytes(long, long)
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobServiceEngine.java b/apex/jobscheduler/framework/java/android/app/job/JobServiceEngine.java
index 697641e..79d87ed 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobServiceEngine.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobServiceEngine.java
@@ -76,6 +76,8 @@
private static final int MSG_UPDATE_ESTIMATED_NETWORK_BYTES = 6;
/** Message that the client wants to give JobScheduler a notification to tie to the job. */
private static final int MSG_SET_NOTIFICATION = 7;
+ /** Message that the network to use has changed. */
+ private static final int MSG_INFORM_OF_NETWORK_CHANGE = 8;
private final IJobService mBinder;
@@ -128,6 +130,16 @@
}
@Override
+ public void onNetworkChanged(JobParameters jobParams) throws RemoteException {
+ JobServiceEngine service = mService.get();
+ if (service != null) {
+ service.mHandler.removeMessages(MSG_INFORM_OF_NETWORK_CHANGE);
+ service.mHandler.obtainMessage(MSG_INFORM_OF_NETWORK_CHANGE, jobParams)
+ .sendToTarget();
+ }
+ }
+
+ @Override
public void stopJob(JobParameters jobParams) throws RemoteException {
JobServiceEngine service = mService.get();
if (service != null) {
@@ -271,6 +283,16 @@
args.recycle();
break;
}
+ case MSG_INFORM_OF_NETWORK_CHANGE: {
+ final JobParameters params = (JobParameters) msg.obj;
+ try {
+ JobServiceEngine.this.onNetworkChanged(params);
+ } catch (Exception e) {
+ Log.e(TAG, "Error while executing job: " + params.getJobId());
+ throw new RuntimeException(e);
+ }
+ break;
+ }
default:
Log.e(TAG, "Unrecognised message received.");
break;
@@ -386,6 +408,15 @@
}
/**
+ * Engine's report that the network for the job has changed.
+ *
+ * @see JobService#onNetworkChanged(JobParameters)
+ */
+ public void onNetworkChanged(@NonNull JobParameters params) {
+ Log.w(TAG, "onNetworkChanged() not implemented. Must override in a subclass.");
+ }
+
+ /**
* Engine's request to get how much data has been downloaded.
*
* @hide
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
index b806ef8..bf8984f 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
@@ -17,6 +17,7 @@
package com.android.server.job;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
+import static android.util.DataUnit.GIGABYTES;
import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX;
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
@@ -58,6 +59,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IBatteryStats;
import com.android.internal.app.procstats.ProcessStats;
+import com.android.internal.util.MemInfoReader;
import com.android.internal.util.StatLogger;
import com.android.server.JobSchedulerBackgroundThread;
import com.android.server.LocalServices;
@@ -85,11 +87,33 @@
private static final boolean DEBUG = JobSchedulerService.DEBUG;
/** The maximum number of concurrent jobs we'll aim to run at one time. */
- public static final int STANDARD_CONCURRENCY_LIMIT = 16;
+ @VisibleForTesting
+ static final int MAX_CONCURRENCY_LIMIT = 64;
/** The maximum number of objects we should retain in memory when not in use. */
- private static final int MAX_RETAINED_OBJECTS = (int) (1.5 * STANDARD_CONCURRENCY_LIMIT);
+ private static final int MAX_RETAINED_OBJECTS = (int) (1.5 * MAX_CONCURRENCY_LIMIT);
static final String CONFIG_KEY_PREFIX_CONCURRENCY = "concurrency_";
+ private static final String KEY_CONCURRENCY_LIMIT = CONFIG_KEY_PREFIX_CONCURRENCY + "limit";
+ @VisibleForTesting
+ static final int DEFAULT_CONCURRENCY_LIMIT;
+
+ static {
+ if (ActivityManager.isLowRamDeviceStatic()) {
+ DEFAULT_CONCURRENCY_LIMIT = 8;
+ } else {
+ final long ramBytes = new MemInfoReader().getTotalSize();
+ if (ramBytes <= GIGABYTES.toBytes(6)) {
+ DEFAULT_CONCURRENCY_LIMIT = 16;
+ } else if (ramBytes <= GIGABYTES.toBytes(8)) {
+ DEFAULT_CONCURRENCY_LIMIT = 20;
+ } else if (ramBytes <= GIGABYTES.toBytes(12)) {
+ DEFAULT_CONCURRENCY_LIMIT = 32;
+ } else {
+ DEFAULT_CONCURRENCY_LIMIT = 40;
+ }
+ }
+ }
+
private static final String KEY_SCREEN_OFF_ADJUSTMENT_DELAY_MS =
CONFIG_KEY_PREFIX_CONCURRENCY + "screen_off_adjustment_delay_ms";
private static final long DEFAULT_SCREEN_OFF_ADJUSTMENT_DELAY_MS = 30_000;
@@ -100,7 +124,7 @@
@VisibleForTesting
static final String KEY_PKG_CONCURRENCY_LIMIT_REGULAR =
CONFIG_KEY_PREFIX_CONCURRENCY + "pkg_concurrency_limit_regular";
- private static final int DEFAULT_PKG_CONCURRENCY_LIMIT_REGULAR = STANDARD_CONCURRENCY_LIMIT / 2;
+ private static final int DEFAULT_PKG_CONCURRENCY_LIMIT_REGULAR = DEFAULT_CONCURRENCY_LIMIT / 2;
@VisibleForTesting
static final String KEY_ENABLE_MAX_WAIT_TIME_BYPASS =
CONFIG_KEY_PREFIX_CONCURRENCY + "enable_max_wait_time_bypass";
@@ -209,84 +233,100 @@
private static final WorkConfigLimitsPerMemoryTrimLevel CONFIG_LIMITS_SCREEN_ON =
new WorkConfigLimitsPerMemoryTrimLevel(
- new WorkTypeConfig("screen_on_normal", 11,
+ new WorkTypeConfig("screen_on_normal", DEFAULT_CONCURRENCY_LIMIT,
+ /* defaultMaxTotal */ DEFAULT_CONCURRENCY_LIMIT * 3 / 4,
// defaultMin
- List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 1),
- Pair.create(WORK_TYPE_EJ, 3), Pair.create(WORK_TYPE_BG, 2),
- Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1)),
+ List.of(Pair.create(WORK_TYPE_TOP, .4f),
+ Pair.create(WORK_TYPE_FGS, .2f),
+ Pair.create(WORK_TYPE_EJ, .2f), Pair.create(WORK_TYPE_BG, .1f),
+ Pair.create(WORK_TYPE_BGUSER_IMPORTANT, .1f)),
// defaultMax
- List.of(Pair.create(WORK_TYPE_BG, 6),
- Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 2),
- Pair.create(WORK_TYPE_BGUSER, 3))
+ List.of(Pair.create(WORK_TYPE_BG, .5f),
+ Pair.create(WORK_TYPE_BGUSER_IMPORTANT, .25f),
+ Pair.create(WORK_TYPE_BGUSER, .2f))
),
- new WorkTypeConfig("screen_on_moderate", 9,
+ new WorkTypeConfig("screen_on_moderate", DEFAULT_CONCURRENCY_LIMIT,
+ /* defaultMaxTotal */ DEFAULT_CONCURRENCY_LIMIT / 2,
// defaultMin
- List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 1),
- Pair.create(WORK_TYPE_EJ, 2), Pair.create(WORK_TYPE_BG, 1),
- Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1)),
+ List.of(Pair.create(WORK_TYPE_TOP, .4f),
+ Pair.create(WORK_TYPE_FGS, .1f),
+ Pair.create(WORK_TYPE_EJ, .1f), Pair.create(WORK_TYPE_BG, .1f),
+ Pair.create(WORK_TYPE_BGUSER_IMPORTANT, .1f)),
// defaultMax
- List.of(Pair.create(WORK_TYPE_BG, 4),
- Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1),
- Pair.create(WORK_TYPE_BGUSER, 1))
+ List.of(Pair.create(WORK_TYPE_BG, .4f),
+ Pair.create(WORK_TYPE_BGUSER_IMPORTANT, .1f),
+ Pair.create(WORK_TYPE_BGUSER, .1f))
),
- new WorkTypeConfig("screen_on_low", 6,
+ new WorkTypeConfig("screen_on_low", DEFAULT_CONCURRENCY_LIMIT,
+ /* defaultMaxTotal */ DEFAULT_CONCURRENCY_LIMIT * 4 / 10,
// defaultMin
- List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 1),
- Pair.create(WORK_TYPE_EJ, 1)),
+ List.of(Pair.create(WORK_TYPE_TOP, 2.0f / 3),
+ Pair.create(WORK_TYPE_FGS, .1f),
+ Pair.create(WORK_TYPE_EJ, .1f)),
// defaultMax
- List.of(Pair.create(WORK_TYPE_BG, 2),
- Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1),
- Pair.create(WORK_TYPE_BGUSER, 1))
+ List.of(Pair.create(WORK_TYPE_BG, 1.0f / 3),
+ Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1.0f / 6),
+ Pair.create(WORK_TYPE_BGUSER, 1.0f / 6))
),
- new WorkTypeConfig("screen_on_critical", 6,
+ new WorkTypeConfig("screen_on_critical", DEFAULT_CONCURRENCY_LIMIT,
+ /* defaultMaxTotal */ DEFAULT_CONCURRENCY_LIMIT * 4 / 10,
// defaultMin
- List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 1),
- Pair.create(WORK_TYPE_EJ, 1)),
+ List.of(Pair.create(WORK_TYPE_TOP, 2.0f / 3),
+ Pair.create(WORK_TYPE_FGS, .1f),
+ Pair.create(WORK_TYPE_EJ, .1f)),
// defaultMax
- List.of(Pair.create(WORK_TYPE_BG, 1),
- Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1),
- Pair.create(WORK_TYPE_BGUSER, 1))
+ List.of(Pair.create(WORK_TYPE_BG, 1.0f / 6),
+ Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1.0f / 6),
+ Pair.create(WORK_TYPE_BGUSER, 1.0f / 6))
)
);
private static final WorkConfigLimitsPerMemoryTrimLevel CONFIG_LIMITS_SCREEN_OFF =
new WorkConfigLimitsPerMemoryTrimLevel(
- new WorkTypeConfig("screen_off_normal", 16,
+ new WorkTypeConfig("screen_off_normal", DEFAULT_CONCURRENCY_LIMIT,
+ /* defaultMaxTotal */ DEFAULT_CONCURRENCY_LIMIT,
// defaultMin
- List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 2),
- Pair.create(WORK_TYPE_EJ, 3), Pair.create(WORK_TYPE_BG, 2),
- Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1)),
+ List.of(Pair.create(WORK_TYPE_TOP, .3f),
+ Pair.create(WORK_TYPE_FGS, .2f),
+ Pair.create(WORK_TYPE_EJ, .3f), Pair.create(WORK_TYPE_BG, .2f),
+ Pair.create(WORK_TYPE_BGUSER_IMPORTANT, .1f)),
// defaultMax
- List.of(Pair.create(WORK_TYPE_BG, 10),
- Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 2),
- Pair.create(WORK_TYPE_BGUSER, 3))
+ List.of(Pair.create(WORK_TYPE_BG, .6f),
+ Pair.create(WORK_TYPE_BGUSER_IMPORTANT, .2f),
+ Pair.create(WORK_TYPE_BGUSER, .2f))
),
- new WorkTypeConfig("screen_off_moderate", 14,
+ new WorkTypeConfig("screen_off_moderate", DEFAULT_CONCURRENCY_LIMIT,
+ /* defaultMaxTotal */ DEFAULT_CONCURRENCY_LIMIT * 9 / 10,
// defaultMin
- List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 2),
- Pair.create(WORK_TYPE_EJ, 3), Pair.create(WORK_TYPE_BG, 2),
- Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1)),
+ List.of(Pair.create(WORK_TYPE_TOP, .3f),
+ Pair.create(WORK_TYPE_FGS, .2f),
+ Pair.create(WORK_TYPE_EJ, .3f), Pair.create(WORK_TYPE_BG, .2f),
+ Pair.create(WORK_TYPE_BGUSER_IMPORTANT, .1f)),
// defaultMax
- List.of(Pair.create(WORK_TYPE_BG, 7),
- Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1),
- Pair.create(WORK_TYPE_BGUSER, 1))
+ List.of(Pair.create(WORK_TYPE_BG, .5f),
+ Pair.create(WORK_TYPE_BGUSER_IMPORTANT, .1f),
+ Pair.create(WORK_TYPE_BGUSER, .1f))
),
- new WorkTypeConfig("screen_off_low", 9,
+ new WorkTypeConfig("screen_off_low", DEFAULT_CONCURRENCY_LIMIT,
+ /* defaultMaxTotal */ DEFAULT_CONCURRENCY_LIMIT * 6 / 10,
// defaultMin
- List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 1),
- Pair.create(WORK_TYPE_EJ, 2), Pair.create(WORK_TYPE_BG, 1)),
+ List.of(Pair.create(WORK_TYPE_TOP, .4f),
+ Pair.create(WORK_TYPE_FGS, .1f),
+ Pair.create(WORK_TYPE_EJ, .2f), Pair.create(WORK_TYPE_BG, .1f)),
// defaultMax
- List.of(Pair.create(WORK_TYPE_BG, 3),
- Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1),
- Pair.create(WORK_TYPE_BGUSER, 1))
+ List.of(Pair.create(WORK_TYPE_BG, .25f),
+ Pair.create(WORK_TYPE_BGUSER_IMPORTANT, .1f),
+ Pair.create(WORK_TYPE_BGUSER, .1f))
),
- new WorkTypeConfig("screen_off_critical", 6,
+ new WorkTypeConfig("screen_off_critical", DEFAULT_CONCURRENCY_LIMIT,
+ /* defaultMaxTotal */ DEFAULT_CONCURRENCY_LIMIT * 4 / 10,
// defaultMin
- List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 1),
- Pair.create(WORK_TYPE_EJ, 1)),
+ List.of(Pair.create(WORK_TYPE_TOP, .5f),
+ Pair.create(WORK_TYPE_FGS, .1f),
+ Pair.create(WORK_TYPE_EJ, .1f)),
// defaultMax
- List.of(Pair.create(WORK_TYPE_BG, 1),
- Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1),
- Pair.create(WORK_TYPE_BGUSER, 1))
+ List.of(Pair.create(WORK_TYPE_BG, .1f),
+ Pair.create(WORK_TYPE_BGUSER_IMPORTANT, .1f),
+ Pair.create(WORK_TYPE_BGUSER, .1f))
)
);
@@ -358,6 +398,12 @@
private long mScreenOffAdjustmentDelayMs = DEFAULT_SCREEN_OFF_ADJUSTMENT_DELAY_MS;
/**
+ * The maximum number of jobs we'll attempt to have running at one time. This may occasionally
+ * be exceeded based on other factors.
+ */
+ private int mSteadyStateConcurrencyLimit = DEFAULT_CONCURRENCY_LIMIT;
+
+ /**
* The maximum number of expedited jobs a single userId-package can have running simultaneously.
* TOP apps are not limited.
*/
@@ -451,7 +497,7 @@
void onThirdPartyAppsCanStart() {
final IBatteryStats batteryStats = IBatteryStats.Stub.asInterface(
ServiceManager.getService(BatteryStats.SERVICE_NAME));
- for (int i = 0; i < STANDARD_CONCURRENCY_LIMIT; i++) {
+ for (int i = 0; i < mSteadyStateConcurrencyLimit; ++i) {
mIdleContexts.add(
mInjector.createJobServiceContext(mService, this,
mNotificationCoordinator, batteryStats,
@@ -778,13 +824,14 @@
}
preferredUidOnly.sort(sDeterminationComparator);
stoppable.sort(sDeterminationComparator);
- for (int i = numRunningJobs; i < STANDARD_CONCURRENCY_LIMIT; ++i) {
+ for (int i = numRunningJobs; i < mSteadyStateConcurrencyLimit; ++i) {
final JobServiceContext jsc;
final int numIdleContexts = mIdleContexts.size();
if (numIdleContexts > 0) {
jsc = mIdleContexts.removeAt(numIdleContexts - 1);
} else {
- Slog.wtf(TAG, "Had fewer than " + STANDARD_CONCURRENCY_LIMIT + " in existence");
+ // This could happen if the config is changed at runtime.
+ Slog.w(TAG, "Had fewer than " + mSteadyStateConcurrencyLimit + " in existence");
jsc = createNewJobServiceContext();
}
@@ -850,7 +897,7 @@
ContextAssignment selectedContext = null;
final int allWorkTypes = getJobWorkTypes(nextPending);
final boolean pkgConcurrencyOkay = !isPkgConcurrencyLimitedLocked(nextPending);
- final boolean isInOverage = projectedRunningCount > STANDARD_CONCURRENCY_LIMIT;
+ final boolean isInOverage = projectedRunningCount > mSteadyStateConcurrencyLimit;
boolean startingJob = false;
if (idle.size() > 0) {
final int idx = idle.size() - 1;
@@ -1132,6 +1179,25 @@
assignJobsToContextsLocked();
}
+ @Nullable
+ @GuardedBy("mLock")
+ JobServiceContext getRunningJobServiceContextLocked(JobStatus job) {
+ if (!mRunningJobs.contains(job)) {
+ return null;
+ }
+
+ for (int i = 0; i < mActiveServices.size(); i++) {
+ JobServiceContext jsc = mActiveServices.get(i);
+ final JobStatus executing = jsc.getRunningJobLocked();
+ if (executing == job) {
+ return jsc;
+ }
+ }
+ Slog.wtf(TAG, "Couldn't find running job on a context");
+ mRunningJobs.remove(job);
+ return null;
+ }
+
@GuardedBy("mLock")
boolean stopJobOnServiceContextLocked(JobStatus job,
@JobParameters.StopReason int reason, int internalReasonCode, String debugReason) {
@@ -1398,7 +1464,7 @@
noteConcurrency();
return;
}
- if (mActiveServices.size() >= STANDARD_CONCURRENCY_LIMIT) {
+ if (mActiveServices.size() >= mSteadyStateConcurrencyLimit) {
final boolean respectConcurrencyLimit;
if (!mMaxWaitTimeBypassEnabled) {
respectConcurrencyLimit = true;
@@ -1801,23 +1867,27 @@
DeviceConfig.Properties properties =
DeviceConfig.getProperties(DeviceConfig.NAMESPACE_JOB_SCHEDULER);
+ // Concurrency limit should be in the range [8, MAX_CONCURRENCY_LIMIT].
+ mSteadyStateConcurrencyLimit = Math.max(8, Math.min(MAX_CONCURRENCY_LIMIT,
+ properties.getInt(KEY_CONCURRENCY_LIMIT, DEFAULT_CONCURRENCY_LIMIT)));
+
mScreenOffAdjustmentDelayMs = properties.getLong(
KEY_SCREEN_OFF_ADJUSTMENT_DELAY_MS, DEFAULT_SCREEN_OFF_ADJUSTMENT_DELAY_MS);
- CONFIG_LIMITS_SCREEN_ON.normal.update(properties);
- CONFIG_LIMITS_SCREEN_ON.moderate.update(properties);
- CONFIG_LIMITS_SCREEN_ON.low.update(properties);
- CONFIG_LIMITS_SCREEN_ON.critical.update(properties);
+ CONFIG_LIMITS_SCREEN_ON.normal.update(properties, mSteadyStateConcurrencyLimit);
+ CONFIG_LIMITS_SCREEN_ON.moderate.update(properties, mSteadyStateConcurrencyLimit);
+ CONFIG_LIMITS_SCREEN_ON.low.update(properties, mSteadyStateConcurrencyLimit);
+ CONFIG_LIMITS_SCREEN_ON.critical.update(properties, mSteadyStateConcurrencyLimit);
- CONFIG_LIMITS_SCREEN_OFF.normal.update(properties);
- CONFIG_LIMITS_SCREEN_OFF.moderate.update(properties);
- CONFIG_LIMITS_SCREEN_OFF.low.update(properties);
- CONFIG_LIMITS_SCREEN_OFF.critical.update(properties);
+ CONFIG_LIMITS_SCREEN_OFF.normal.update(properties, mSteadyStateConcurrencyLimit);
+ CONFIG_LIMITS_SCREEN_OFF.moderate.update(properties, mSteadyStateConcurrencyLimit);
+ CONFIG_LIMITS_SCREEN_OFF.low.update(properties, mSteadyStateConcurrencyLimit);
+ CONFIG_LIMITS_SCREEN_OFF.critical.update(properties, mSteadyStateConcurrencyLimit);
- // Package concurrency limits must in the range [1, STANDARD_CONCURRENCY_LIMIT].
- mPkgConcurrencyLimitEj = Math.max(1, Math.min(STANDARD_CONCURRENCY_LIMIT,
+ // Package concurrency limits must in the range [1, mSteadyStateConcurrencyLimit].
+ mPkgConcurrencyLimitEj = Math.max(1, Math.min(mSteadyStateConcurrencyLimit,
properties.getInt(KEY_PKG_CONCURRENCY_LIMIT_EJ, DEFAULT_PKG_CONCURRENCY_LIMIT_EJ)));
- mPkgConcurrencyLimitRegular = Math.max(1, Math.min(STANDARD_CONCURRENCY_LIMIT,
+ mPkgConcurrencyLimitRegular = Math.max(1, Math.min(mSteadyStateConcurrencyLimit,
properties.getInt(
KEY_PKG_CONCURRENCY_LIMIT_REGULAR, DEFAULT_PKG_CONCURRENCY_LIMIT_REGULAR)));
@@ -1838,6 +1908,7 @@
try {
pw.println("Configuration:");
pw.increaseIndent();
+ pw.print(KEY_CONCURRENCY_LIMIT, mSteadyStateConcurrencyLimit).println();
pw.print(KEY_SCREEN_OFF_ADJUSTMENT_DELAY_MS, mScreenOffAdjustmentDelayMs).println();
pw.print(KEY_PKG_CONCURRENCY_LIMIT_EJ, mPkgConcurrencyLimitEj).println();
pw.print(KEY_PKG_CONCURRENCY_LIMIT_REGULAR, mPkgConcurrencyLimitRegular).println();
@@ -2041,130 +2112,181 @@
@VisibleForTesting
static class WorkTypeConfig {
- @VisibleForTesting
- static final String KEY_PREFIX_MAX = CONFIG_KEY_PREFIX_CONCURRENCY + "max_";
- @VisibleForTesting
- static final String KEY_PREFIX_MIN = CONFIG_KEY_PREFIX_CONCURRENCY + "min_";
+ private static final String KEY_PREFIX_MAX = CONFIG_KEY_PREFIX_CONCURRENCY + "max_";
+ private static final String KEY_PREFIX_MIN = CONFIG_KEY_PREFIX_CONCURRENCY + "min_";
@VisibleForTesting
static final String KEY_PREFIX_MAX_TOTAL = CONFIG_KEY_PREFIX_CONCURRENCY + "max_total_";
- private static final String KEY_PREFIX_MAX_TOP = CONFIG_KEY_PREFIX_CONCURRENCY + "max_top_";
- private static final String KEY_PREFIX_MAX_FGS = CONFIG_KEY_PREFIX_CONCURRENCY + "max_fgs_";
- private static final String KEY_PREFIX_MAX_EJ = CONFIG_KEY_PREFIX_CONCURRENCY + "max_ej_";
- private static final String KEY_PREFIX_MAX_BG = CONFIG_KEY_PREFIX_CONCURRENCY + "max_bg_";
- private static final String KEY_PREFIX_MAX_BGUSER =
- CONFIG_KEY_PREFIX_CONCURRENCY + "max_bguser_";
- private static final String KEY_PREFIX_MAX_BGUSER_IMPORTANT =
- CONFIG_KEY_PREFIX_CONCURRENCY + "max_bguser_important_";
- private static final String KEY_PREFIX_MIN_TOP = CONFIG_KEY_PREFIX_CONCURRENCY + "min_top_";
- private static final String KEY_PREFIX_MIN_FGS = CONFIG_KEY_PREFIX_CONCURRENCY + "min_fgs_";
- private static final String KEY_PREFIX_MIN_EJ = CONFIG_KEY_PREFIX_CONCURRENCY + "min_ej_";
- private static final String KEY_PREFIX_MIN_BG = CONFIG_KEY_PREFIX_CONCURRENCY + "min_bg_";
- private static final String KEY_PREFIX_MIN_BGUSER =
- CONFIG_KEY_PREFIX_CONCURRENCY + "min_bguser_";
- private static final String KEY_PREFIX_MIN_BGUSER_IMPORTANT =
- CONFIG_KEY_PREFIX_CONCURRENCY + "min_bguser_important_";
+ @VisibleForTesting
+ static final String KEY_PREFIX_MAX_RATIO = KEY_PREFIX_MAX + "ratio_";
+ private static final String KEY_PREFIX_MAX_RATIO_TOP = KEY_PREFIX_MAX_RATIO + "top_";
+ private static final String KEY_PREFIX_MAX_RATIO_FGS = KEY_PREFIX_MAX_RATIO + "fgs_";
+ private static final String KEY_PREFIX_MAX_RATIO_EJ = KEY_PREFIX_MAX_RATIO + "ej_";
+ private static final String KEY_PREFIX_MAX_RATIO_BG = KEY_PREFIX_MAX_RATIO + "bg_";
+ private static final String KEY_PREFIX_MAX_RATIO_BGUSER = KEY_PREFIX_MAX_RATIO + "bguser_";
+ private static final String KEY_PREFIX_MAX_RATIO_BGUSER_IMPORTANT =
+ KEY_PREFIX_MAX_RATIO + "bguser_important_";
+ @VisibleForTesting
+ static final String KEY_PREFIX_MIN_RATIO = KEY_PREFIX_MIN + "ratio_";
+ private static final String KEY_PREFIX_MIN_RATIO_TOP = KEY_PREFIX_MIN_RATIO + "top_";
+ private static final String KEY_PREFIX_MIN_RATIO_FGS = KEY_PREFIX_MIN_RATIO + "fgs_";
+ private static final String KEY_PREFIX_MIN_RATIO_EJ = KEY_PREFIX_MIN_RATIO + "ej_";
+ private static final String KEY_PREFIX_MIN_RATIO_BG = KEY_PREFIX_MIN_RATIO + "bg_";
+ private static final String KEY_PREFIX_MIN_RATIO_BGUSER = KEY_PREFIX_MIN_RATIO + "bguser_";
+ private static final String KEY_PREFIX_MIN_RATIO_BGUSER_IMPORTANT =
+ KEY_PREFIX_MIN_RATIO + "bguser_important_";
private final String mConfigIdentifier;
private int mMaxTotal;
private final SparseIntArray mMinReservedSlots = new SparseIntArray(NUM_WORK_TYPES);
private final SparseIntArray mMaxAllowedSlots = new SparseIntArray(NUM_WORK_TYPES);
private final int mDefaultMaxTotal;
- private final SparseIntArray mDefaultMinReservedSlots = new SparseIntArray(NUM_WORK_TYPES);
- private final SparseIntArray mDefaultMaxAllowedSlots = new SparseIntArray(NUM_WORK_TYPES);
+ // We use SparseIntArrays to store floats because there is currently no SparseFloatArray
+ // available, and it doesn't seem worth it to add such a data structure just for this
+ // use case. We don't use SparseDoubleArrays because DeviceConfig only supports floats and
+ // converting between floats and ints is more straightforward than floats and doubles.
+ private final SparseIntArray mDefaultMinReservedSlotsRatio =
+ new SparseIntArray(NUM_WORK_TYPES);
+ private final SparseIntArray mDefaultMaxAllowedSlotsRatio =
+ new SparseIntArray(NUM_WORK_TYPES);
- WorkTypeConfig(@NonNull String configIdentifier, int defaultMaxTotal,
- List<Pair<Integer, Integer>> defaultMin, List<Pair<Integer, Integer>> defaultMax) {
+ WorkTypeConfig(@NonNull String configIdentifier,
+ int steadyStateConcurrencyLimit, int defaultMaxTotal,
+ List<Pair<Integer, Float>> defaultMinRatio,
+ List<Pair<Integer, Float>> defaultMaxRatio) {
mConfigIdentifier = configIdentifier;
- mDefaultMaxTotal = mMaxTotal = Math.min(defaultMaxTotal, STANDARD_CONCURRENCY_LIMIT);
+ mDefaultMaxTotal = mMaxTotal = Math.min(defaultMaxTotal, steadyStateConcurrencyLimit);
int numReserved = 0;
- for (int i = defaultMin.size() - 1; i >= 0; --i) {
- mDefaultMinReservedSlots.put(defaultMin.get(i).first, defaultMin.get(i).second);
- numReserved += defaultMin.get(i).second;
+ for (int i = defaultMinRatio.size() - 1; i >= 0; --i) {
+ final float ratio = defaultMinRatio.get(i).second;
+ final int wt = defaultMinRatio.get(i).first;
+ if (ratio < 0 || 1 <= ratio) {
+ // 1 means to reserve everything. This shouldn't be allowed.
+ // We only create new configs on boot, so this should trigger during development
+ // (before the code gets checked in), so this makes sure the hard-coded defaults
+ // make sense. DeviceConfig values will be handled gracefully in update().
+ throw new IllegalArgumentException("Invalid default min ratio: wt=" + wt
+ + " minRatio=" + ratio);
+ }
+ mDefaultMinReservedSlotsRatio.put(wt, Float.floatToRawIntBits(ratio));
+ numReserved += mMaxTotal * ratio;
}
if (mDefaultMaxTotal < 0 || numReserved > mDefaultMaxTotal) {
// We only create new configs on boot, so this should trigger during development
// (before the code gets checked in), so this makes sure the hard-coded defaults
// make sense. DeviceConfig values will be handled gracefully in update().
throw new IllegalArgumentException("Invalid default config: t=" + defaultMaxTotal
- + " min=" + defaultMin + " max=" + defaultMax);
+ + " min=" + defaultMinRatio + " max=" + defaultMaxRatio);
}
- for (int i = defaultMax.size() - 1; i >= 0; --i) {
- mDefaultMaxAllowedSlots.put(defaultMax.get(i).first, defaultMax.get(i).second);
+ for (int i = defaultMaxRatio.size() - 1; i >= 0; --i) {
+ final float ratio = defaultMaxRatio.get(i).second;
+ final int wt = defaultMaxRatio.get(i).first;
+ final float minRatio =
+ Float.intBitsToFloat(mDefaultMinReservedSlotsRatio.get(wt, 0));
+ if (ratio < minRatio || ratio <= 0) {
+ // Max ratio shouldn't be <= 0 or less than minRatio.
+ throw new IllegalArgumentException("Invalid default config:"
+ + " t=" + defaultMaxTotal
+ + " min=" + defaultMinRatio + " max=" + defaultMaxRatio);
+ }
+ mDefaultMaxAllowedSlotsRatio.put(wt, Float.floatToRawIntBits(ratio));
}
update(new DeviceConfig.Properties.Builder(
- DeviceConfig.NAMESPACE_JOB_SCHEDULER).build());
+ DeviceConfig.NAMESPACE_JOB_SCHEDULER).build(), steadyStateConcurrencyLimit);
}
- void update(@NonNull DeviceConfig.Properties properties) {
- // Ensure total in the range [1, STANDARD_CONCURRENCY_LIMIT].
- mMaxTotal = Math.max(1, Math.min(STANDARD_CONCURRENCY_LIMIT,
+ void update(@NonNull DeviceConfig.Properties properties, int steadyStateConcurrencyLimit) {
+ // Ensure total in the range [1, mSteadyStateConcurrencyLimit].
+ mMaxTotal = Math.max(1, Math.min(steadyStateConcurrencyLimit,
properties.getInt(KEY_PREFIX_MAX_TOTAL + mConfigIdentifier, mDefaultMaxTotal)));
+ final int oneIntBits = Float.floatToIntBits(1);
+
mMaxAllowedSlots.clear();
// Ensure they're in the range [1, total].
- final int maxTop = Math.max(1, Math.min(mMaxTotal,
- properties.getInt(KEY_PREFIX_MAX_TOP + mConfigIdentifier,
- mDefaultMaxAllowedSlots.get(WORK_TYPE_TOP, mMaxTotal))));
+ final int maxTop = getMaxValue(properties,
+ KEY_PREFIX_MAX_RATIO_TOP + mConfigIdentifier, WORK_TYPE_TOP, oneIntBits);
mMaxAllowedSlots.put(WORK_TYPE_TOP, maxTop);
- final int maxFgs = Math.max(1, Math.min(mMaxTotal,
- properties.getInt(KEY_PREFIX_MAX_FGS + mConfigIdentifier,
- mDefaultMaxAllowedSlots.get(WORK_TYPE_FGS, mMaxTotal))));
+ final int maxFgs = getMaxValue(properties,
+ KEY_PREFIX_MAX_RATIO_FGS + mConfigIdentifier, WORK_TYPE_FGS, oneIntBits);
mMaxAllowedSlots.put(WORK_TYPE_FGS, maxFgs);
- final int maxEj = Math.max(1, Math.min(mMaxTotal,
- properties.getInt(KEY_PREFIX_MAX_EJ + mConfigIdentifier,
- mDefaultMaxAllowedSlots.get(WORK_TYPE_EJ, mMaxTotal))));
+ final int maxEj = getMaxValue(properties,
+ KEY_PREFIX_MAX_RATIO_EJ + mConfigIdentifier, WORK_TYPE_EJ, oneIntBits);
mMaxAllowedSlots.put(WORK_TYPE_EJ, maxEj);
- final int maxBg = Math.max(1, Math.min(mMaxTotal,
- properties.getInt(KEY_PREFIX_MAX_BG + mConfigIdentifier,
- mDefaultMaxAllowedSlots.get(WORK_TYPE_BG, mMaxTotal))));
+ final int maxBg = getMaxValue(properties,
+ KEY_PREFIX_MAX_RATIO_BG + mConfigIdentifier, WORK_TYPE_BG, oneIntBits);
mMaxAllowedSlots.put(WORK_TYPE_BG, maxBg);
- final int maxBgUserImp = Math.max(1, Math.min(mMaxTotal,
- properties.getInt(KEY_PREFIX_MAX_BGUSER_IMPORTANT + mConfigIdentifier,
- mDefaultMaxAllowedSlots.get(WORK_TYPE_BGUSER_IMPORTANT, mMaxTotal))));
+ final int maxBgUserImp = getMaxValue(properties,
+ KEY_PREFIX_MAX_RATIO_BGUSER_IMPORTANT + mConfigIdentifier,
+ WORK_TYPE_BGUSER_IMPORTANT, oneIntBits);
mMaxAllowedSlots.put(WORK_TYPE_BGUSER_IMPORTANT, maxBgUserImp);
- final int maxBgUser = Math.max(1, Math.min(mMaxTotal,
- properties.getInt(KEY_PREFIX_MAX_BGUSER + mConfigIdentifier,
- mDefaultMaxAllowedSlots.get(WORK_TYPE_BGUSER, mMaxTotal))));
+ final int maxBgUser = getMaxValue(properties,
+ KEY_PREFIX_MAX_RATIO_BGUSER + mConfigIdentifier, WORK_TYPE_BGUSER, oneIntBits);
mMaxAllowedSlots.put(WORK_TYPE_BGUSER, maxBgUser);
int remaining = mMaxTotal;
mMinReservedSlots.clear();
// Ensure top is in the range [1, min(maxTop, total)]
- final int minTop = Math.max(1, Math.min(Math.min(maxTop, mMaxTotal),
- properties.getInt(KEY_PREFIX_MIN_TOP + mConfigIdentifier,
- mDefaultMinReservedSlots.get(WORK_TYPE_TOP))));
+ final int minTop = getMinValue(properties,
+ KEY_PREFIX_MIN_RATIO_TOP + mConfigIdentifier, WORK_TYPE_TOP,
+ 1, Math.min(maxTop, mMaxTotal));
mMinReservedSlots.put(WORK_TYPE_TOP, minTop);
remaining -= minTop;
// Ensure fgs is in the range [0, min(maxFgs, remaining)]
- final int minFgs = Math.max(0, Math.min(Math.min(maxFgs, remaining),
- properties.getInt(KEY_PREFIX_MIN_FGS + mConfigIdentifier,
- mDefaultMinReservedSlots.get(WORK_TYPE_FGS))));
+ final int minFgs = getMinValue(properties,
+ KEY_PREFIX_MIN_RATIO_FGS + mConfigIdentifier, WORK_TYPE_FGS,
+ 0, Math.min(maxFgs, remaining));
mMinReservedSlots.put(WORK_TYPE_FGS, minFgs);
remaining -= minFgs;
// Ensure ej is in the range [0, min(maxEj, remaining)]
- final int minEj = Math.max(0, Math.min(Math.min(maxEj, remaining),
- properties.getInt(KEY_PREFIX_MIN_EJ + mConfigIdentifier,
- mDefaultMinReservedSlots.get(WORK_TYPE_EJ))));
+ final int minEj = getMinValue(properties,
+ KEY_PREFIX_MIN_RATIO_EJ + mConfigIdentifier, WORK_TYPE_EJ,
+ 0, Math.min(maxEj, remaining));
mMinReservedSlots.put(WORK_TYPE_EJ, minEj);
remaining -= minEj;
// Ensure bg is in the range [0, min(maxBg, remaining)]
- final int minBg = Math.max(0, Math.min(Math.min(maxBg, remaining),
- properties.getInt(KEY_PREFIX_MIN_BG + mConfigIdentifier,
- mDefaultMinReservedSlots.get(WORK_TYPE_BG))));
+ final int minBg = getMinValue(properties,
+ KEY_PREFIX_MIN_RATIO_BG + mConfigIdentifier, WORK_TYPE_BG,
+ 0, Math.min(maxBg, remaining));
mMinReservedSlots.put(WORK_TYPE_BG, minBg);
remaining -= minBg;
// Ensure bg user imp is in the range [0, min(maxBgUserImp, remaining)]
- final int minBgUserImp = Math.max(0, Math.min(Math.min(maxBgUserImp, remaining),
- properties.getInt(KEY_PREFIX_MIN_BGUSER_IMPORTANT + mConfigIdentifier,
- mDefaultMinReservedSlots.get(WORK_TYPE_BGUSER_IMPORTANT, 0))));
+ final int minBgUserImp = getMinValue(properties,
+ KEY_PREFIX_MIN_RATIO_BGUSER_IMPORTANT + mConfigIdentifier,
+ WORK_TYPE_BGUSER_IMPORTANT, 0, Math.min(maxBgUserImp, remaining));
mMinReservedSlots.put(WORK_TYPE_BGUSER_IMPORTANT, minBgUserImp);
+ remaining -= minBgUserImp;
// Ensure bg user is in the range [0, min(maxBgUser, remaining)]
- final int minBgUser = Math.max(0, Math.min(Math.min(maxBgUser, remaining),
- properties.getInt(KEY_PREFIX_MIN_BGUSER + mConfigIdentifier,
- mDefaultMinReservedSlots.get(WORK_TYPE_BGUSER, 0))));
+ final int minBgUser = getMinValue(properties,
+ KEY_PREFIX_MIN_RATIO_BGUSER + mConfigIdentifier, WORK_TYPE_BGUSER,
+ 0, Math.min(maxBgUser, remaining));
mMinReservedSlots.put(WORK_TYPE_BGUSER, minBgUser);
}
+ /**
+ * Return the calculated max value for the work type.
+ * @param defaultFloatInIntBits A {@code float} value in int bits representation (using
+ * {@link Float#floatToIntBits(float)}.
+ */
+ private int getMaxValue(@NonNull DeviceConfig.Properties properties, @NonNull String key,
+ int workType, int defaultFloatInIntBits) {
+ final float maxRatio = Math.min(1, properties.getFloat(key,
+ Float.intBitsToFloat(
+ mDefaultMaxAllowedSlotsRatio.get(workType, defaultFloatInIntBits))));
+ // Max values should be in the range [1, total].
+ return Math.max(1, (int) (mMaxTotal * maxRatio));
+ }
+
+ /**
+ * Return the calculated min value for the work type.
+ */
+ private int getMinValue(@NonNull DeviceConfig.Properties properties, @NonNull String key,
+ int workType, int lowerLimit, int upperLimit) {
+ final float minRatio = Math.min(1,
+ properties.getFloat(key,
+ Float.intBitsToFloat(mDefaultMinReservedSlotsRatio.get(workType))));
+ return Math.max(lowerLimit, Math.min(upperLimit, (int) (mMaxTotal * minRatio)));
+ }
+
int getMaxTotal() {
return mMaxTotal;
}
@@ -2179,29 +2301,37 @@
void dump(IndentingPrintWriter pw) {
pw.print(KEY_PREFIX_MAX_TOTAL + mConfigIdentifier, mMaxTotal).println();
- pw.print(KEY_PREFIX_MIN_TOP + mConfigIdentifier, mMinReservedSlots.get(WORK_TYPE_TOP))
+ pw.print(KEY_PREFIX_MIN_RATIO_TOP + mConfigIdentifier,
+ mMinReservedSlots.get(WORK_TYPE_TOP))
.println();
- pw.print(KEY_PREFIX_MAX_TOP + mConfigIdentifier, mMaxAllowedSlots.get(WORK_TYPE_TOP))
+ pw.print(KEY_PREFIX_MAX_RATIO_TOP + mConfigIdentifier,
+ mMaxAllowedSlots.get(WORK_TYPE_TOP))
.println();
- pw.print(KEY_PREFIX_MIN_FGS + mConfigIdentifier, mMinReservedSlots.get(WORK_TYPE_FGS))
+ pw.print(KEY_PREFIX_MIN_RATIO_FGS + mConfigIdentifier,
+ mMinReservedSlots.get(WORK_TYPE_FGS))
.println();
- pw.print(KEY_PREFIX_MAX_FGS + mConfigIdentifier, mMaxAllowedSlots.get(WORK_TYPE_FGS))
+ pw.print(KEY_PREFIX_MAX_RATIO_FGS + mConfigIdentifier,
+ mMaxAllowedSlots.get(WORK_TYPE_FGS))
.println();
- pw.print(KEY_PREFIX_MIN_EJ + mConfigIdentifier, mMinReservedSlots.get(WORK_TYPE_EJ))
+ pw.print(KEY_PREFIX_MIN_RATIO_EJ + mConfigIdentifier,
+ mMinReservedSlots.get(WORK_TYPE_EJ))
.println();
- pw.print(KEY_PREFIX_MAX_EJ + mConfigIdentifier, mMaxAllowedSlots.get(WORK_TYPE_EJ))
+ pw.print(KEY_PREFIX_MAX_RATIO_EJ + mConfigIdentifier,
+ mMaxAllowedSlots.get(WORK_TYPE_EJ))
.println();
- pw.print(KEY_PREFIX_MIN_BG + mConfigIdentifier, mMinReservedSlots.get(WORK_TYPE_BG))
+ pw.print(KEY_PREFIX_MIN_RATIO_BG + mConfigIdentifier,
+ mMinReservedSlots.get(WORK_TYPE_BG))
.println();
- pw.print(KEY_PREFIX_MAX_BG + mConfigIdentifier, mMaxAllowedSlots.get(WORK_TYPE_BG))
+ pw.print(KEY_PREFIX_MAX_RATIO_BG + mConfigIdentifier,
+ mMaxAllowedSlots.get(WORK_TYPE_BG))
.println();
- pw.print(KEY_PREFIX_MIN_BGUSER + mConfigIdentifier,
+ pw.print(KEY_PREFIX_MIN_RATIO_BGUSER + mConfigIdentifier,
mMinReservedSlots.get(WORK_TYPE_BGUSER_IMPORTANT)).println();
- pw.print(KEY_PREFIX_MAX_BGUSER + mConfigIdentifier,
+ pw.print(KEY_PREFIX_MAX_RATIO_BGUSER + mConfigIdentifier,
mMaxAllowedSlots.get(WORK_TYPE_BGUSER_IMPORTANT)).println();
- pw.print(KEY_PREFIX_MIN_BGUSER + mConfigIdentifier,
+ pw.print(KEY_PREFIX_MIN_RATIO_BGUSER + mConfigIdentifier,
mMinReservedSlots.get(WORK_TYPE_BGUSER)).println();
- pw.print(KEY_PREFIX_MAX_BGUSER + mConfigIdentifier,
+ pw.print(KEY_PREFIX_MAX_RATIO_BGUSER + mConfigIdentifier,
mMaxAllowedSlots.get(WORK_TYPE_BGUSER)).println();
}
}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index 4e52ed3..43f7279 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -61,6 +61,7 @@
import android.content.pm.ParceledListSlice;
import android.content.pm.ProviderInfo;
import android.content.pm.ServiceInfo;
+import android.net.Network;
import android.net.Uri;
import android.os.BatteryManager;
import android.os.BatteryManagerInternal;
@@ -152,6 +153,7 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.concurrent.CountDownLatch;
import java.util.function.Consumer;
import java.util.function.Predicate;
@@ -241,6 +243,7 @@
final Object mLock = new Object();
/** Master list of jobs. */
final JobStore mJobs;
+ private final CountDownLatch mJobStoreLoadedLatch;
/** Tracking the standby bucket state of each app */
final StandbyTracker mStandbyTracker;
/** Tracking amount of time each package runs for. */
@@ -1940,6 +1943,17 @@
}
@Override
+ public void onNetworkChanged(JobStatus jobStatus, Network newNetwork) {
+ synchronized (mLock) {
+ final JobServiceContext jsc =
+ mConcurrencyManager.getRunningJobServiceContextLocked(jobStatus);
+ if (jsc != null) {
+ jsc.informOfNetworkChangeLocked(newNetwork);
+ }
+ }
+ }
+
+ @Override
public void onRestrictedBucketChanged(List<JobStatus> jobs) {
final int len = jobs.size();
if (len == 0) {
@@ -2032,7 +2046,9 @@
publishLocalService(JobSchedulerInternal.class, new LocalService());
// Initialize the job store and set up any persisted jobs
- mJobs = JobStore.initAndGet(this);
+ mJobStoreLoadedLatch = new CountDownLatch(1);
+ mJobs = JobStore.get(this);
+ mJobs.initAsync(mJobStoreLoadedLatch);
mBatteryStateTracker = new BatteryStateTracker();
mBatteryStateTracker.startTracking();
@@ -2100,7 +2116,7 @@
// And kick off the work to update the affected jobs, using a secondary
// thread instead of chugging away here on the main looper thread.
- new Thread(mJobTimeUpdater, "JobSchedulerTimeSetReceiver").start();
+ mJobs.runWorkAsync(mJobTimeUpdater);
}
}
}
@@ -2138,7 +2154,15 @@
@Override
public void onBootPhase(int phase) {
- if (PHASE_SYSTEM_SERVICES_READY == phase) {
+ if (PHASE_LOCK_SETTINGS_READY == phase) {
+ // This is the last phase before PHASE_SYSTEM_SERVICES_READY. We need to ensure that
+ // persisted jobs are loaded before we can proceed to PHASE_SYSTEM_SERVICES_READY.
+ try {
+ mJobStoreLoadedLatch.await();
+ } catch (InterruptedException e) {
+ Slog.e(TAG, "Couldn't wait on job store loading latch");
+ }
+ } else if (PHASE_SYSTEM_SERVICES_READY == phase) {
mConstantsObserver.start();
for (StateController controller : mControllers) {
controller.onSystemServicesReady();
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
index ce7da86..fb5d63e 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
@@ -36,6 +36,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
+import android.net.Network;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
@@ -187,6 +188,8 @@
private int mPendingInternalStopReason;
private String mPendingDebugStopReason;
+ private Network mPendingNetworkChange;
+
// Debugging: reason this job was last stopped.
public String mStoppedReason;
@@ -292,6 +295,7 @@
mRunningJob = job;
mRunningJobWorkType = workType;
mRunningCallback = new JobCallback();
+ mPendingNetworkChange = null;
final boolean isDeadlineExpired =
job.hasDeadlineConstraint() &&
(job.getLatestRunTimeElapsed() < sElapsedRealtimeClock.millis());
@@ -515,6 +519,28 @@
return Math.max(0, mExecutionStartTimeElapsed + mMinExecutionGuaranteeMillis - nowElapsed);
}
+ void informOfNetworkChangeLocked(Network newNetwork) {
+ if (mVerb != VERB_EXECUTING) {
+ Slog.w(TAG, "Sending onNetworkChanged for a job that isn't started. " + mRunningJob);
+ if (mVerb == VERB_BINDING || mVerb == VERB_STARTING) {
+ // The network changed before the job has fully started. Hold the change push
+ // until the job has started executing.
+ mPendingNetworkChange = newNetwork;
+ }
+ return;
+ }
+ try {
+ mParams.setNetwork(newNetwork);
+ mPendingNetworkChange = null;
+ service.onNetworkChanged(mParams);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Error sending onNetworkChanged to client.", e);
+ // The job's host app apparently crashed during the job, so we should reschedule.
+ closeAndCleanupJobLocked(/* reschedule */ true,
+ "host crashed when trying to inform of network change");
+ }
+ }
+
boolean isWithinExecutionGuaranteeTime() {
return sElapsedRealtimeClock.millis()
< mExecutionStartTimeElapsed + mMinExecutionGuaranteeMillis;
@@ -972,6 +998,10 @@
return;
}
scheduleOpTimeOutLocked();
+ if (mPendingNetworkChange != null
+ && !Objects.equals(mParams.getNetwork(), mPendingNetworkChange)) {
+ informOfNetworkChangeLocked(mPendingNetworkChange);
+ }
if (mRunningJob.isUserVisibleJob()) {
mService.informObserversOfUserVisibleJobChange(this, mRunningJob, true);
}
@@ -1193,7 +1223,7 @@
completedJob.isConstraintSatisfied(JobStatus.CONSTRAINT_CONTENT_TRIGGER));
if (Trace.isTagEnabled(Trace.TRACE_TAG_SYSTEM_SERVER)) {
Trace.asyncTraceForTrackEnd(Trace.TRACE_TAG_SYSTEM_SERVER, "JobScheduler",
- completedJob.getTag(), getId());
+ getId());
}
try {
mBatteryStats.noteJobFinish(mRunningJob.getBatteryName(), mRunningJob.getSourceUid(),
@@ -1225,6 +1255,7 @@
mPendingStopReason = JobParameters.STOP_REASON_UNDEFINED;
mPendingInternalStopReason = 0;
mPendingDebugStopReason = null;
+ mPendingNetworkChange = null;
removeOpTimeOutLocked();
if (completedJob.isUserVisibleJob()) {
mService.informObserversOfUserVisibleJobChange(this, completedJob, false);
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobStore.java b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
index 9ec74e5..0dcb0b245 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
@@ -70,6 +70,7 @@
import java.util.Objects;
import java.util.Set;
import java.util.StringJoiner;
+import java.util.concurrent.CountDownLatch;
import java.util.function.Consumer;
import java.util.function.Predicate;
@@ -131,7 +132,7 @@
private JobStorePersistStats mPersistInfo = new JobStorePersistStats();
/** Used by the {@link JobSchedulerService} to instantiate the JobStore. */
- static JobStore initAndGet(JobSchedulerService jobManagerService) {
+ static JobStore get(JobSchedulerService jobManagerService) {
synchronized (sSingletonLock) {
if (sSingleton == null) {
sSingleton = new JobStore(jobManagerService.getContext(),
@@ -147,6 +148,7 @@
@VisibleForTesting
public static JobStore initAndGetForTesting(Context context, File dataDir) {
JobStore jobStoreUnderTest = new JobStore(context, new Object(), dataDir);
+ jobStoreUnderTest.init();
jobStoreUnderTest.clearForTesting();
return jobStoreUnderTest;
}
@@ -181,10 +183,16 @@
mXmlTimestamp = mJobsFile.exists()
? mJobsFile.getLastModifiedTime() : mJobFileDirectory.lastModified();
mRtcGood = (sSystemClock.millis() > mXmlTimestamp);
+ }
+ private void init() {
readJobMapFromDisk(mJobSet, mRtcGood);
}
+ void initAsync(CountDownLatch completionLatch) {
+ mIoHandler.post(new ReadJobMapFromDiskRunnable(mJobSet, mRtcGood, completionLatch));
+ }
+
private AtomicFile createJobFile(String baseName) {
return createJobFile(new File(mJobFileDirectory, baseName + ".xml"));
}
@@ -202,6 +210,15 @@
}
/**
+ * Runs any necessary work asynchronously. If this is called after
+ * {@link #initAsync(CountDownLatch)}, this ensures the given work runs after
+ * the JobStore is initialized.
+ */
+ void runWorkAsync(@NonNull Runnable r) {
+ mIoHandler.post(r);
+ }
+
+ /**
* Find all the jobs that were affected by RTC clock uncertainty at boot time. Returns
* parallel lists of the existing JobStatus objects and of new, equivalent JobStatus instances
* with now-corrected time bounds.
@@ -998,14 +1015,21 @@
private final class ReadJobMapFromDiskRunnable implements Runnable {
private final JobSet jobSet;
private final boolean rtcGood;
+ private final CountDownLatch mCompletionLatch;
/**
* @param jobSet Reference to the (empty) set of JobStatus objects that back the JobStore,
* so that after disk read we can populate it directly.
*/
ReadJobMapFromDiskRunnable(JobSet jobSet, boolean rtcIsGood) {
+ this(jobSet, rtcIsGood, null);
+ }
+
+ ReadJobMapFromDiskRunnable(JobSet jobSet, boolean rtcIsGood,
+ @Nullable CountDownLatch completionLatch) {
this.jobSet = jobSet;
this.rtcGood = rtcIsGood;
+ this.mCompletionLatch = completionLatch;
}
@Override
@@ -1088,6 +1112,9 @@
if (needFileMigration) {
migrateJobFilesAsync();
}
+ if (mCompletionLatch != null) {
+ mCompletionLatch.countDown();
+ }
}
private List<JobStatus> readJobMapImpl(InputStream fis, boolean rtcIsGood, long nowElapsed)
diff --git a/apex/jobscheduler/service/java/com/android/server/job/StateChangedListener.java b/apex/jobscheduler/service/java/com/android/server/job/StateChangedListener.java
index 554f152..50064bd 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/StateChangedListener.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/StateChangedListener.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.net.Network;
import android.util.ArraySet;
import com.android.server.job.controllers.JobStatus;
@@ -57,6 +58,8 @@
public void onDeviceIdleStateChanged(boolean deviceIdle);
+ void onNetworkChanged(JobStatus jobStatus, Network newNetwork);
+
/**
* Called when these jobs are added or removed from the
* {@link android.app.usage.UsageStatsManager#STANDBY_BUCKET_RESTRICTED} bucket.
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
index b491291..16f5c7f 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
@@ -1125,6 +1125,17 @@
mFlexibilityController.isFlexibilitySatisfiedLocked(jobStatus));
}
+ // Try to handle network transitions in a reasonable manner. See the lengthy note inside
+ // UidDefaultNetworkCallback for more details.
+ if (!changed && satisfied && jobStatus.network != null
+ && mService.isCurrentlyRunningLocked(jobStatus)) {
+ // The job's connectivity constraint continues to be satisfied even though the network
+ // has changed.
+ // Inform the job of the new network so that it can attempt to switch over. This is the
+ // ideal behavior for certain transitions such as going from a metered network to an
+ // unmetered network.
+ mStateChangedListener.onNetworkChanged(jobStatus, network);
+ }
// Pass along the evaluated network for job to use; prevents race
// conditions as default routes change over time, and opens the door to
@@ -1419,8 +1430,8 @@
// the onBlockedStatusChanged() call, we re-evaluate the job, but keep it running
// (assuming the new network satisfies constraints). The app continues to use the old
// network (if they use the network object provided through JobParameters.getNetwork())
- // because we don't notify them of the default network change. If the old network no
- // longer satisfies requested constraints, then we have a problem. Depending on the order
+ // because we don't notify them of the default network change. If the old network later
+ // stops satisfying requested constraints, then we have a problem. Depending on the order
// of calls, if the per-UID callback gets notified of the network change before the
// general callback gets notified of the capabilities change, then the job's network
// object will point to the new network and we won't stop the job, even though we told it
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
index 0b875cc..a2e8eb4 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
@@ -2098,7 +2098,7 @@
} else {
sb.append(" satisfied:0x").append(Integer.toHexString(satisfiedConstraints));
sb.append(" unsatisfied:0x").append(Integer.toHexString(
- (satisfiedConstraints & mRequiredConstraintsOfInterest)
+ (satisfiedConstraints & (mRequiredConstraintsOfInterest | IMPLICIT_CONSTRAINTS))
^ mRequiredConstraintsOfInterest));
}
sb.append("}");
diff --git a/boot/Android.bp b/boot/Android.bp
index c9a3bd0..d4a6500 100644
--- a/boot/Android.bp
+++ b/boot/Android.bp
@@ -23,6 +23,18 @@
default_applicable_licenses: ["frameworks_base_license"],
}
+soong_config_module_type {
+ name: "custom_platform_bootclasspath",
+ module_type: "platform_bootclasspath",
+ config_namespace: "AUTO",
+ bool_variables: [
+ "car_bootclasspath_fragment",
+ ],
+ properties: [
+ "fragments",
+ ],
+}
+
// This module provides access to information Soong has related to the
// whole platform bootclasspath. Currently, that information is provided solely
// through configuration but additional information will be added here.
@@ -41,7 +53,7 @@
//
// This module needs to be present in the build for the above processing to be
// done correctly.
-platform_bootclasspath {
+custom_platform_bootclasspath {
name: "platform-bootclasspath",
// The bootclasspath_fragments that contribute to the platform
@@ -127,17 +139,24 @@
apex: "com.android.wifi",
module: "com.android.wifi-bootclasspath-fragment",
},
- // only used for auto
- {
- apex: "com.android.car.framework",
- module: "com.android.car.framework-bootclasspath-fragment",
- },
{
apex: "com.android.virt",
module: "com.android.virt-bootclasspath-fragment",
},
],
+ soong_config_variables: {
+ car_bootclasspath_fragment: {
+ fragments: [
+ // only used for auto
+ {
+ apex: "com.android.car.framework",
+ module: "com.android.car.framework-bootclasspath-fragment",
+ },
+ ],
+ },
+ },
+
// Additional information needed by hidden api processing.
hidden_api: {
unsupported: [
diff --git a/core/api/current.txt b/core/api/current.txt
index ead6637..4b1335e 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -89,6 +89,7 @@
field public static final String DISABLE_KEYGUARD = "android.permission.DISABLE_KEYGUARD";
field public static final String DUMP = "android.permission.DUMP";
field public static final String ENFORCE_UPDATE_OWNERSHIP = "android.permission.ENFORCE_UPDATE_OWNERSHIP";
+ field public static final String EXECUTE_APP_ACTION = "android.permission.EXECUTE_APP_ACTION";
field public static final String EXPAND_STATUS_BAR = "android.permission.EXPAND_STATUS_BAR";
field public static final String FACTORY_TEST = "android.permission.FACTORY_TEST";
field public static final String FOREGROUND_SERVICE = "android.permission.FOREGROUND_SERVICE";
@@ -385,6 +386,7 @@
field public static final int allowTaskReparenting = 16843268; // 0x1010204
field public static final int allowUndo = 16843999; // 0x10104df
field public static final int allowUntrustedActivityEmbedding = 16844393; // 0x1010669
+ field public static final int allowUpdateOwnership;
field public static final int alpha = 16843551; // 0x101031f
field public static final int alphabeticModifiers = 16844110; // 0x101054e
field public static final int alphabeticShortcut = 16843235; // 0x10101e3
@@ -743,6 +745,7 @@
field public static final int focusableInTouchMode = 16842971; // 0x10100db
field public static final int focusedByDefault = 16844100; // 0x1010544
field @Deprecated public static final int focusedMonthDateColor = 16843587; // 0x1010343
+ field public static final int focusedSearchResultHighlightColor;
field public static final int font = 16844082; // 0x1010532
field public static final int fontFamily = 16843692; // 0x10103ac
field public static final int fontFeatureSettings = 16843959; // 0x10104b7
@@ -918,6 +921,7 @@
field public static final int isAlwaysSyncable = 16843571; // 0x1010333
field public static final int isAsciiCapable = 16843753; // 0x10103e9
field public static final int isAuxiliary = 16843647; // 0x101037f
+ field public static final int isCredential;
field public static final int isDefault = 16843297; // 0x1010221
field public static final int isFeatureSplit = 16844123; // 0x101055b
field public static final int isGame = 16843764; // 0x10103f4
@@ -1353,6 +1357,7 @@
field public static final int searchHintIcon = 16843988; // 0x10104d4
field public static final int searchIcon = 16843907; // 0x1010483
field public static final int searchMode = 16843221; // 0x10101d5
+ field public static final int searchResultHighlightColor;
field public static final int searchSettingsDescription = 16843402; // 0x101028a
field public static final int searchSuggestAuthority = 16843222; // 0x10101d6
field public static final int searchSuggestIntentAction = 16843225; // 0x10101d9
@@ -5904,7 +5909,7 @@
ctor public LocaleConfig(@NonNull android.content.Context);
ctor public LocaleConfig(@NonNull android.os.LocaleList);
method public int describeContents();
- method @NonNull public static android.app.LocaleConfig fromResources(@NonNull android.content.Context);
+ method @NonNull public static android.app.LocaleConfig fromContextIgnoringOverride(@NonNull android.content.Context);
method public int getStatus();
method @Nullable public android.os.LocaleList getSupportedLocales();
method public void writeToParcel(@NonNull android.os.Parcel, int);
@@ -6128,7 +6133,7 @@
}
public static class Notification.Action implements android.os.Parcelable {
- ctor @Deprecated public Notification.Action(int, CharSequence, android.app.PendingIntent);
+ ctor @Deprecated public Notification.Action(int, CharSequence, @Nullable android.app.PendingIntent);
method public android.app.Notification.Action clone();
method public int describeContents();
method public boolean getAllowGeneratedReplies();
@@ -6158,8 +6163,8 @@
}
public static final class Notification.Action.Builder {
- ctor @Deprecated public Notification.Action.Builder(int, CharSequence, android.app.PendingIntent);
- ctor public Notification.Action.Builder(android.graphics.drawable.Icon, CharSequence, android.app.PendingIntent);
+ ctor @Deprecated public Notification.Action.Builder(int, CharSequence, @Nullable android.app.PendingIntent);
+ ctor public Notification.Action.Builder(android.graphics.drawable.Icon, CharSequence, @Nullable android.app.PendingIntent);
ctor public Notification.Action.Builder(android.app.Notification.Action);
method @NonNull public android.app.Notification.Action.Builder addExtras(android.os.Bundle);
method @NonNull public android.app.Notification.Action.Builder addRemoteInput(android.app.RemoteInput);
@@ -8060,6 +8065,7 @@
method public int getNetworkId();
method public boolean isEnabled();
method public boolean isFallbackToDefaultConnectionAllowed();
+ method public boolean shouldBlockNonMatchingNetworks();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.app.admin.PreferentialNetworkServiceConfig> CREATOR;
field public static final int PREFERENTIAL_NETWORK_ID_1 = 1; // 0x1
@@ -8077,6 +8083,7 @@
method @NonNull public android.app.admin.PreferentialNetworkServiceConfig.Builder setFallbackToDefaultConnectionAllowed(boolean);
method @NonNull public android.app.admin.PreferentialNetworkServiceConfig.Builder setIncludedUids(@NonNull int[]);
method @NonNull public android.app.admin.PreferentialNetworkServiceConfig.Builder setNetworkId(int);
+ method @NonNull public android.app.admin.PreferentialNetworkServiceConfig.Builder setShouldBlockNonMatchingNetworks(boolean);
}
public class SecurityLog {
@@ -8561,6 +8568,7 @@
method public int getClipGrantFlags();
method @NonNull public android.os.PersistableBundle getExtras();
method public int getJobId();
+ method @Nullable public String getJobNamespace();
method @Nullable public android.net.Network getNetwork();
method public int getStopReason();
method @NonNull public android.os.Bundle getTransientExtras();
@@ -8594,10 +8602,14 @@
method public boolean canRunLongJobs();
method public abstract void cancel(int);
method public abstract void cancelAll();
+ method public void cancelInAllNamespaces();
method public abstract int enqueue(@NonNull android.app.job.JobInfo, @NonNull android.app.job.JobWorkItem);
+ method @NonNull public android.app.job.JobScheduler forNamespace(@NonNull String);
method @NonNull public abstract java.util.List<android.app.job.JobInfo> getAllPendingJobs();
+ method @Nullable public String getNamespace();
method @Nullable public abstract android.app.job.JobInfo getPendingJob(int);
method public int getPendingJobReason(int);
+ method @NonNull public java.util.Map<java.lang.String,java.util.List<android.app.job.JobInfo>> getPendingJobsInAllNamespaces();
method public abstract int schedule(@NonNull android.app.job.JobInfo);
field public static final int PENDING_JOB_REASON_APP = 1; // 0x1
field public static final int PENDING_JOB_REASON_APP_STANDBY = 2; // 0x2
@@ -8625,6 +8637,7 @@
ctor public JobService();
method public final void jobFinished(android.app.job.JobParameters, boolean);
method public final android.os.IBinder onBind(android.content.Intent);
+ method public void onNetworkChanged(@NonNull android.app.job.JobParameters);
method public abstract boolean onStartJob(android.app.job.JobParameters);
method public abstract boolean onStopJob(android.app.job.JobParameters);
method public final void setNotification(@NonNull android.app.job.JobParameters, int, @NonNull android.app.Notification, int);
@@ -8639,6 +8652,7 @@
ctor public JobServiceEngine(android.app.Service);
method public final android.os.IBinder getBinder();
method public void jobFinished(android.app.job.JobParameters, boolean);
+ method public void onNetworkChanged(@NonNull android.app.job.JobParameters);
method public abstract boolean onStartJob(android.app.job.JobParameters);
method public abstract boolean onStopJob(android.app.job.JobParameters);
method public void setNotification(@NonNull android.app.job.JobParameters, int, @NonNull android.app.Notification, int);
@@ -9230,15 +9244,18 @@
}
public final class CompanionDeviceManager {
+ method @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public void addOnAssociationsChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.companion.CompanionDeviceManager.OnAssociationsChangedListener);
method @RequiresPermission(anyOf={android.Manifest.permission.REQUEST_COMPANION_PROFILE_WATCH, android.Manifest.permission.REQUEST_COMPANION_PROFILE_COMPUTER, android.Manifest.permission.REQUEST_COMPANION_PROFILE_APP_STREAMING, android.Manifest.permission.REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION}, conditional=true) public void associate(@NonNull android.companion.AssociationRequest, @NonNull android.companion.CompanionDeviceManager.Callback, @Nullable android.os.Handler);
method @RequiresPermission(anyOf={android.Manifest.permission.REQUEST_COMPANION_PROFILE_WATCH, android.Manifest.permission.REQUEST_COMPANION_PROFILE_COMPUTER, android.Manifest.permission.REQUEST_COMPANION_PROFILE_APP_STREAMING, android.Manifest.permission.REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION}, conditional=true) public void associate(@NonNull android.companion.AssociationRequest, @NonNull java.util.concurrent.Executor, @NonNull android.companion.CompanionDeviceManager.Callback);
method @Nullable public android.content.IntentSender buildAssociationCancellationIntent();
method @Nullable public android.content.IntentSender buildPermissionTransferUserConsentIntent(int) throws android.companion.DeviceNotAssociatedException;
method @Deprecated public void disassociate(@NonNull String);
method public void disassociate(int);
+ method @NonNull @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public java.util.List<android.companion.AssociationInfo> getAllAssociations();
method @Deprecated @NonNull public java.util.List<java.lang.String> getAssociations();
method @NonNull public java.util.List<android.companion.AssociationInfo> getMyAssociations();
method @Deprecated public boolean hasNotificationAccess(android.content.ComponentName);
+ method @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public void removeOnAssociationsChangedListener(@NonNull android.companion.CompanionDeviceManager.OnAssociationsChangedListener);
method public void requestNotificationAccess(android.content.ComponentName);
method @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) public void startObservingDevicePresence(@NonNull String) throws android.companion.DeviceNotAssociatedException;
method @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) public void stopObservingDevicePresence(@NonNull String) throws android.companion.DeviceNotAssociatedException;
@@ -9259,6 +9276,10 @@
method public abstract void onFailure(@Nullable CharSequence);
}
+ public static interface CompanionDeviceManager.OnAssociationsChangedListener {
+ method public void onAssociationsChanged(@NonNull java.util.List<android.companion.AssociationInfo>);
+ }
+
public abstract class CompanionDeviceService extends android.app.Service {
ctor public CompanionDeviceService();
method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
@@ -10600,7 +10621,6 @@
field public static final String ACTION_SEND_MULTIPLE = "android.intent.action.SEND_MULTIPLE";
field public static final String ACTION_SET_WALLPAPER = "android.intent.action.SET_WALLPAPER";
field public static final String ACTION_SHOW_APP_INFO = "android.intent.action.SHOW_APP_INFO";
- field public static final String ACTION_SHOW_OUTPUT_SWITCHER = "android.intent.action.SHOW_OUTPUT_SWITCHER";
field public static final String ACTION_SHOW_WORK_APPS = "android.intent.action.SHOW_WORK_APPS";
field public static final String ACTION_SHUTDOWN = "android.intent.action.ACTION_SHUTDOWN";
field public static final String ACTION_SYNC = "android.intent.action.SYNC";
@@ -11875,6 +11895,7 @@
public class PackageInstaller {
method public void abandonSession(int);
method public void checkInstallConstraints(@NonNull java.util.List<java.lang.String>, @NonNull android.content.pm.PackageInstaller.InstallConstraints, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.content.pm.PackageInstaller.InstallConstraintsResult>);
+ method public void commitSessionAfterInstallConstraintsAreMet(int, @NonNull android.content.IntentSender, @NonNull android.content.pm.PackageInstaller.InstallConstraints, long);
method public int createSession(@NonNull android.content.pm.PackageInstaller.SessionParams) throws java.io.IOException;
method @Deprecated @Nullable public android.content.pm.PackageInstaller.SessionInfo getActiveStagedSession();
method @NonNull public java.util.List<android.content.pm.PackageInstaller.SessionInfo> getActiveStagedSessions();
@@ -11919,6 +11940,7 @@
field public static final int STATUS_FAILURE_INCOMPATIBLE = 7; // 0x7
field public static final int STATUS_FAILURE_INVALID = 4; // 0x4
field public static final int STATUS_FAILURE_STORAGE = 6; // 0x6
+ field public static final int STATUS_FAILURE_TIMEOUT = 8; // 0x8
field public static final int STATUS_PENDING_USER_ACTION = -1; // 0xffffffff
field public static final int STATUS_SUCCESS = 0; // 0x0
}
@@ -11981,7 +12003,7 @@
method @NonNull public int[] getChildSessionIds();
method @NonNull public String[] getNames() throws java.io.IOException;
method public int getParentSessionId();
- method public boolean isKeepApplicationEnabledSetting();
+ method public boolean isApplicationEnabledSettingPersistent();
method public boolean isMultiPackage();
method public boolean isRequestUpdateOwnership();
method public boolean isStaged();
@@ -12036,8 +12058,8 @@
method @NonNull public android.os.UserHandle getUser();
method public boolean hasParentSessionId();
method public boolean isActive();
+ method public boolean isApplicationEnabledSettingPersistent();
method public boolean isCommitted();
- method public boolean isKeepApplicationEnabledSetting();
method public boolean isMultiPackage();
method public boolean isRequestUpdateOwnership();
method public boolean isSealed();
@@ -12067,12 +12089,12 @@
method public void setAppIcon(@Nullable android.graphics.Bitmap);
method public void setAppLabel(@Nullable CharSequence);
method public void setAppPackageName(@Nullable String);
+ method public void setApplicationEnabledSettingPersistent();
method @Deprecated public void setAutoRevokePermissionsMode(boolean);
method public void setInstallLocation(int);
method public void setInstallReason(int);
method public void setInstallScenario(int);
method public void setInstallerPackageName(@Nullable String);
- method public void setKeepApplicationEnabledSetting();
method public void setMultiPackage();
method public void setOriginatingUid(int);
method public void setOriginatingUri(@Nullable android.net.Uri);
@@ -12257,6 +12279,7 @@
method @NonNull public java.util.List<android.content.pm.PackageManager.Property> queryProviderProperty(@NonNull String);
method @NonNull public java.util.List<android.content.pm.PackageManager.Property> queryReceiverProperty(@NonNull String);
method @NonNull public java.util.List<android.content.pm.PackageManager.Property> queryServiceProperty(@NonNull String);
+ method public void relinquishUpdateOwnership(@NonNull String);
method @Deprecated public abstract void removePackageFromPreferred(@NonNull String);
method public abstract void removePermission(@NonNull String);
method @RequiresPermission(value="android.permission.WHITELIST_RESTRICTED_PERMISSIONS", conditional=true) public boolean removeWhitelistedRestrictedPermission(@NonNull String, @NonNull String, int);
@@ -12690,8 +12713,8 @@
field public static final int FLAG_STOP_WITH_TASK = 1; // 0x1
field public static final int FLAG_USE_APP_ZYGOTE = 8; // 0x8
field @RequiresPermission(allOf={android.Manifest.permission.FOREGROUND_SERVICE_CAMERA}, anyOf={android.Manifest.permission.CAMERA}, conditional=true) public static final int FOREGROUND_SERVICE_TYPE_CAMERA = 64; // 0x40
- field @RequiresPermission(allOf={android.Manifest.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE}, anyOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.CHANGE_NETWORK_STATE, android.Manifest.permission.CHANGE_WIFI_STATE, android.Manifest.permission.CHANGE_WIFI_MULTICAST_STATE, android.Manifest.permission.NFC, android.Manifest.permission.TRANSMIT_IR}, conditional=true) public static final int FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE = 16; // 0x10
- field @Deprecated @RequiresPermission(value=android.Manifest.permission.FOREGROUND_SERVICE_DATA_SYNC, conditional=true) public static final int FOREGROUND_SERVICE_TYPE_DATA_SYNC = 1; // 0x1
+ field @RequiresPermission(allOf={android.Manifest.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE}, anyOf={android.Manifest.permission.BLUETOOTH_ADVERTISE, android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_SCAN, android.Manifest.permission.CHANGE_NETWORK_STATE, android.Manifest.permission.CHANGE_WIFI_STATE, android.Manifest.permission.CHANGE_WIFI_MULTICAST_STATE, android.Manifest.permission.NFC, android.Manifest.permission.TRANSMIT_IR, android.Manifest.permission.UWB_RANGING}, conditional=true) public static final int FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE = 16; // 0x10
+ field @RequiresPermission(value=android.Manifest.permission.FOREGROUND_SERVICE_DATA_SYNC, conditional=true) public static final int FOREGROUND_SERVICE_TYPE_DATA_SYNC = 1; // 0x1
field @RequiresPermission(android.Manifest.permission.FOREGROUND_SERVICE_FILE_MANAGEMENT) public static final int FOREGROUND_SERVICE_TYPE_FILE_MANAGEMENT = 4096; // 0x1000
field @RequiresPermission(allOf={android.Manifest.permission.FOREGROUND_SERVICE_HEALTH}, anyOf={android.Manifest.permission.ACTIVITY_RECOGNITION, android.Manifest.permission.BODY_SENSORS, android.Manifest.permission.HIGH_SAMPLING_RATE_SENSORS}) public static final int FOREGROUND_SERVICE_TYPE_HEALTH = 256; // 0x100
field @RequiresPermission(allOf={android.Manifest.permission.FOREGROUND_SERVICE_LOCATION}, anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}, conditional=true) public static final int FOREGROUND_SERVICE_TYPE_LOCATION = 8; // 0x8
@@ -13354,9 +13377,8 @@
public final class GetCredentialResponse implements android.os.Parcelable {
ctor public GetCredentialResponse(@NonNull android.credentials.Credential);
- ctor public GetCredentialResponse();
method public int describeContents();
- method @Nullable public android.credentials.Credential getCredential();
+ method @NonNull public android.credentials.Credential getCredential();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.credentials.GetCredentialResponse> CREATOR;
}
@@ -18218,7 +18240,7 @@
method public int capture(@NonNull android.hardware.camera2.CaptureRequest, @NonNull java.util.concurrent.Executor, @NonNull android.hardware.camera2.CameraExtensionSession.ExtensionCaptureCallback) throws android.hardware.camera2.CameraAccessException;
method public void close() throws android.hardware.camera2.CameraAccessException;
method @NonNull public android.hardware.camera2.CameraDevice getDevice();
- method @Nullable public android.util.Pair<java.lang.Long,java.lang.Long> getRealtimeStillCaptureLatency() throws android.hardware.camera2.CameraAccessException;
+ method @Nullable public android.hardware.camera2.CameraExtensionSession.StillCaptureLatency getRealtimeStillCaptureLatency() throws android.hardware.camera2.CameraAccessException;
method public int setRepeatingRequest(@NonNull android.hardware.camera2.CaptureRequest, @NonNull java.util.concurrent.Executor, @NonNull android.hardware.camera2.CameraExtensionSession.ExtensionCaptureCallback) throws android.hardware.camera2.CameraAccessException;
method public void stopRepeating() throws android.hardware.camera2.CameraAccessException;
}
@@ -18241,6 +18263,12 @@
method public abstract void onConfigured(@NonNull android.hardware.camera2.CameraExtensionSession);
}
+ public static final class CameraExtensionSession.StillCaptureLatency {
+ ctor public CameraExtensionSession.StillCaptureLatency(long, long);
+ method public long getCaptureLatency();
+ method public long getProcessingLatency();
+ }
+
public final class CameraManager {
method @NonNull public android.hardware.camera2.CameraCharacteristics getCameraCharacteristics(@NonNull String) throws android.hardware.camera2.CameraAccessException;
method @NonNull public android.hardware.camera2.CameraExtensionCharacteristics getCameraExtensionCharacteristics(@NonNull String) throws android.hardware.camera2.CameraAccessException;
@@ -25792,7 +25820,7 @@
}
public final class MediaProjectionConfig implements android.os.Parcelable {
- method @NonNull public static android.media.projection.MediaProjectionConfig createConfigForDisplay(@IntRange(from=android.view.Display.DEFAULT_DISPLAY, to=android.view.Display.DEFAULT_DISPLAY) int);
+ method @NonNull public static android.media.projection.MediaProjectionConfig createConfigForDefaultDisplay();
method @NonNull public static android.media.projection.MediaProjectionConfig createConfigForUserChoice();
method public int describeContents();
method public void writeToParcel(@NonNull android.os.Parcel, int);
@@ -28359,24 +28387,15 @@
public final class NfcAdapter {
method public void disableForegroundDispatch(android.app.Activity);
- method @Deprecated public void disableForegroundNdefPush(android.app.Activity);
method public void disableReaderMode(android.app.Activity);
method public void enableForegroundDispatch(android.app.Activity, android.app.PendingIntent, android.content.IntentFilter[], String[][]);
- method @Deprecated public void enableForegroundNdefPush(android.app.Activity, android.nfc.NdefMessage);
method public void enableReaderMode(android.app.Activity, android.nfc.NfcAdapter.ReaderCallback, int, android.os.Bundle);
method public static android.nfc.NfcAdapter getDefaultAdapter(android.content.Context);
method @Nullable public android.nfc.NfcAntennaInfo getNfcAntennaInfo();
method public boolean ignore(android.nfc.Tag, int, android.nfc.NfcAdapter.OnTagRemovedListener, android.os.Handler);
- method @Deprecated public boolean invokeBeam(android.app.Activity);
method public boolean isEnabled();
- method @Deprecated public boolean isNdefPushEnabled();
method public boolean isSecureNfcEnabled();
method public boolean isSecureNfcSupported();
- method @Deprecated public void setBeamPushUris(android.net.Uri[], android.app.Activity);
- method @Deprecated public void setBeamPushUrisCallback(android.nfc.NfcAdapter.CreateBeamUrisCallback, android.app.Activity);
- method @Deprecated public void setNdefPushMessage(android.nfc.NdefMessage, android.app.Activity, android.app.Activity...);
- method @Deprecated public void setNdefPushMessageCallback(android.nfc.NfcAdapter.CreateNdefMessageCallback, android.app.Activity, android.app.Activity...);
- method @Deprecated public void setOnNdefPushCompleteCallback(android.nfc.NfcAdapter.OnNdefPushCompleteCallback, android.app.Activity, android.app.Activity...);
field public static final String ACTION_ADAPTER_STATE_CHANGED = "android.nfc.action.ADAPTER_STATE_CHANGED";
field public static final String ACTION_NDEF_DISCOVERED = "android.nfc.action.NDEF_DISCOVERED";
field @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public static final String ACTION_PREFERRED_PAYMENT_CHANGED = "android.nfc.action.PREFERRED_PAYMENT_CHANGED";
@@ -28408,18 +28427,6 @@
field public static final int STATE_TURNING_ON = 2; // 0x2
}
- @Deprecated public static interface NfcAdapter.CreateBeamUrisCallback {
- method @Deprecated public android.net.Uri[] createBeamUris(android.nfc.NfcEvent);
- }
-
- @Deprecated public static interface NfcAdapter.CreateNdefMessageCallback {
- method @Deprecated public android.nfc.NdefMessage createNdefMessage(android.nfc.NfcEvent);
- }
-
- @Deprecated public static interface NfcAdapter.OnNdefPushCompleteCallback {
- method @Deprecated public void onNdefPushComplete(android.nfc.NfcEvent);
- }
-
public static interface NfcAdapter.OnTagRemovedListener {
method public void onTagRemoved();
}
@@ -31674,7 +31681,8 @@
method public static void scaleM(float[], int, float, float, float);
method public static void setIdentityM(float[], int);
method public static void setLookAtM(float[], int, float, float, float, float, float, float, float, float, float);
- method public static void setRotateEulerM(float[], int, float, float, float);
+ method @Deprecated public static void setRotateEulerM(float[], int, float, float, float);
+ method public static void setRotateEulerM2(@NonNull float[], int, float, float, float);
method public static void setRotateM(float[], int, float, float, float, float);
method public static void translateM(float[], int, float[], int, float, float, float);
method public static void translateM(float[], int, float, float, float);
@@ -33210,6 +33218,7 @@
field public static final String DISALLOW_CONFIG_CELL_BROADCASTS = "no_config_cell_broadcasts";
field public static final String DISALLOW_CONFIG_CREDENTIALS = "no_config_credentials";
field public static final String DISALLOW_CONFIG_DATE_TIME = "no_config_date_time";
+ field public static final String DISALLOW_CONFIG_DEFAULT_APPS = "disallow_config_default_apps";
field public static final String DISALLOW_CONFIG_LOCALE = "no_config_locale";
field public static final String DISALLOW_CONFIG_LOCATION = "no_config_location";
field public static final String DISALLOW_CONFIG_MOBILE_NETWORKS = "no_config_mobile_networks";
@@ -36392,7 +36401,6 @@
field public static final String ACTION_MANAGE_ALL_SIM_PROFILES_SETTINGS = "android.settings.MANAGE_ALL_SIM_PROFILES_SETTINGS";
field public static final String ACTION_MANAGE_APPLICATIONS_SETTINGS = "android.settings.MANAGE_APPLICATIONS_SETTINGS";
field public static final String ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION = "android.settings.MANAGE_APP_ALL_FILES_ACCESS_PERMISSION";
- field public static final String ACTION_MANAGE_APP_LONG_RUNNING_JOBS = "android.settings.MANAGE_APP_LONG_RUNNING_JOBS";
field public static final String ACTION_MANAGE_DEFAULT_APPS_SETTINGS = "android.settings.MANAGE_DEFAULT_APPS_SETTINGS";
field public static final String ACTION_MANAGE_OVERLAY_PERMISSION = "android.settings.action.MANAGE_OVERLAY_PERMISSION";
field public static final String ACTION_MANAGE_SUPERVISOR_RESTRICTED_SETTING = "android.settings.MANAGE_SUPERVISOR_RESTRICTED_SETTING";
@@ -39229,9 +39237,13 @@
method @NonNull public android.service.autofill.FillResponse.Builder setFlags(int);
method @NonNull public android.service.autofill.FillResponse.Builder setFooter(@NonNull android.widget.RemoteViews);
method @NonNull public android.service.autofill.FillResponse.Builder setHeader(@NonNull android.widget.RemoteViews);
+ method @NonNull public android.service.autofill.FillResponse.Builder setIconResourceId(@DrawableRes int);
method @NonNull public android.service.autofill.FillResponse.Builder setIgnoredIds(android.view.autofill.AutofillId...);
method @NonNull public android.service.autofill.FillResponse.Builder setPresentationCancelIds(@Nullable int[]);
method @NonNull public android.service.autofill.FillResponse.Builder setSaveInfo(@NonNull android.service.autofill.SaveInfo);
+ method @NonNull public android.service.autofill.FillResponse.Builder setServiceDisplayNameResourceId(@StringRes int);
+ method @NonNull public android.service.autofill.FillResponse.Builder setShowFillDialogIcon(boolean);
+ method @NonNull public android.service.autofill.FillResponse.Builder setShowSaveDialogIcon(boolean);
method @NonNull public android.service.autofill.FillResponse.Builder setUserData(@NonNull android.service.autofill.UserData);
}
@@ -39936,6 +39948,7 @@
method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent);
method public abstract void onClearCredentialState(@NonNull android.service.credentials.ClearCredentialStateRequest, @NonNull android.os.CancellationSignal, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.credentials.ClearCredentialStateException>);
field public static final String CAPABILITY_META_DATA_KEY = "android.credentials.capabilities";
+ field public static final String EXTRA_BEGIN_GET_CREDENTIAL_REQUEST = "android.service.credentials.extra.BEGIN_GET_CREDENTIAL_REQUEST";
field public static final String EXTRA_CREATE_CREDENTIAL_EXCEPTION = "android.service.credentials.extra.CREATE_CREDENTIAL_EXCEPTION";
field public static final String EXTRA_CREATE_CREDENTIAL_REQUEST = "android.service.credentials.extra.CREATE_CREDENTIAL_REQUEST";
field public static final String EXTRA_CREATE_CREDENTIAL_RESPONSE = "android.service.credentials.extra.CREATE_CREDENTIAL_RESPONSE";
@@ -40515,11 +40528,14 @@
method public android.os.IBinder onBind(android.content.Intent);
method @NonNull public java.util.Set<java.lang.String> onGetSupportedVoiceActions(@NonNull java.util.Set<java.lang.String>);
method public void onLaunchVoiceAssistFromKeyguard();
+ method public void onPrepareToShowSession(@NonNull android.os.Bundle, int);
method public void onReady();
+ method public void onShowSessionFailed(@NonNull android.os.Bundle);
method public void onShutdown();
method public void setDisabledShowContext(int);
method public final void setUiHints(@NonNull android.os.Bundle);
method public void showSession(android.os.Bundle, int);
+ field public static final String KEY_SHOW_SESSION_ID = "android.service.voice.SHOW_SESSION_ID";
field public static final String SERVICE_INTERFACE = "android.service.voice.VoiceInteractionService";
field public static final String SERVICE_META_DATA = "android.voice_interaction";
}
@@ -42754,6 +42770,7 @@
field public static final String KEY_SHOW_VIDEO_CALL_CHARGES_ALERT_DIALOG_BOOL = "show_video_call_charges_alert_dialog_bool";
field public static final String KEY_SHOW_WFC_LOCATION_PRIVACY_POLICY_BOOL = "show_wfc_location_privacy_policy_bool";
field @Deprecated public static final String KEY_SIMPLIFIED_NETWORK_SETTINGS_BOOL = "simplified_network_settings_bool";
+ field public static final String KEY_SIM_COUNTRY_ISO_OVERRIDE_STRING = "sim_country_iso_override_string";
field public static final String KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL = "sim_network_unlock_allow_dismiss_bool";
field public static final String KEY_SMDP_SERVER_ADDRESS_STRING = "smdp_server_address_string";
field public static final String KEY_SMS_REQUIRES_DESTINATION_NUMBER_CONVERSION_BOOL = "sms_requires_destination_number_conversion_bool";
@@ -44896,7 +44913,7 @@
method public boolean isVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle);
method public boolean isWorldPhone();
method @Deprecated public void listen(android.telephony.PhoneStateListener, int);
- method @RequiresPermission(android.Manifest.permission.READ_BASIC_PHONE_STATE) public void purchasePremiumCapability(int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+ method @RequiresPermission(allOf={android.Manifest.permission.READ_BASIC_PHONE_STATE, android.Manifest.permission.INTERNET}) public void purchasePremiumCapability(int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void rebootModem();
method public void registerTelephonyCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyCallback);
method public void registerTelephonyCallback(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyCallback);
@@ -45077,7 +45094,7 @@
field public static final int PURCHASE_PREMIUM_CAPABILITY_RESULT_FEATURE_NOT_SUPPORTED = 10; // 0xa
field public static final int PURCHASE_PREMIUM_CAPABILITY_RESULT_NETWORK_NOT_AVAILABLE = 12; // 0xc
field public static final int PURCHASE_PREMIUM_CAPABILITY_RESULT_NOT_DEFAULT_DATA_SUBSCRIPTION = 14; // 0xe
- field public static final int PURCHASE_PREMIUM_CAPABILITY_RESULT_OVERRIDDEN = 5; // 0x5
+ field public static final int PURCHASE_PREMIUM_CAPABILITY_RESULT_NOT_FOREGROUND = 5; // 0x5
field public static final int PURCHASE_PREMIUM_CAPABILITY_RESULT_PENDING_NETWORK_SETUP = 15; // 0xf
field public static final int PURCHASE_PREMIUM_CAPABILITY_RESULT_REQUEST_FAILED = 11; // 0xb
field public static final int PURCHASE_PREMIUM_CAPABILITY_RESULT_SUCCESS = 1; // 0x1
@@ -46632,8 +46649,8 @@
field public static final int DONE = -1; // 0xffffffff
}
- public static class SegmentFinder.DefaultSegmentFinder extends android.text.SegmentFinder {
- ctor public SegmentFinder.DefaultSegmentFinder(@NonNull int[]);
+ public static class SegmentFinder.PrescribedSegmentFinder extends android.text.SegmentFinder {
+ ctor public SegmentFinder.PrescribedSegmentFinder(@NonNull int[]);
method public int nextEndBoundary(@IntRange(from=0) int);
method public int nextStartBoundary(@IntRange(from=0) int);
method public int previousEndBoundary(@IntRange(from=0) int);
@@ -50556,6 +50573,7 @@
field public static final int AXIS_GENERIC_7 = 38; // 0x26
field public static final int AXIS_GENERIC_8 = 39; // 0x27
field public static final int AXIS_GENERIC_9 = 40; // 0x28
+ field public static final int AXIS_GESTURE_PINCH_SCALE_FACTOR = 52; // 0x34
field public static final int AXIS_GESTURE_SCROLL_X_DISTANCE = 50; // 0x32
field public static final int AXIS_GESTURE_SCROLL_Y_DISTANCE = 51; // 0x33
field public static final int AXIS_GESTURE_X_OFFSET = 48; // 0x30
@@ -50596,6 +50614,7 @@
field public static final int CLASSIFICATION_AMBIGUOUS_GESTURE = 1; // 0x1
field public static final int CLASSIFICATION_DEEP_PRESS = 2; // 0x2
field public static final int CLASSIFICATION_NONE = 0; // 0x0
+ field public static final int CLASSIFICATION_PINCH = 5; // 0x5
field public static final int CLASSIFICATION_TWO_FINGER_SWIPE = 3; // 0x3
field @NonNull public static final android.os.Parcelable.Creator<android.view.MotionEvent> CREATOR;
field public static final int EDGE_BOTTOM = 2; // 0x2
@@ -50640,6 +50659,13 @@
field public int toolType;
}
+ public final class MotionPredictor {
+ ctor public MotionPredictor(@NonNull android.content.Context);
+ method public boolean isPredictionAvailable(int, int);
+ method @NonNull public java.util.List<android.view.MotionEvent> predict(long);
+ method public void record(@NonNull android.view.MotionEvent);
+ }
+
public interface OnReceiveContentListener {
method @Nullable public android.view.ContentInfo onReceiveContent(@NonNull android.view.View, @NonNull android.view.ContentInfo);
}
@@ -51412,6 +51438,7 @@
method public boolean isAutoHandwritingEnabled();
method public boolean isClickable();
method public boolean isContextClickable();
+ method public boolean isCredential();
method public boolean isDirty();
method @Deprecated public boolean isDrawingCacheEnabled();
method public boolean isDuplicateParentStateEnabled();
@@ -51645,6 +51672,7 @@
method public void setImportantForAccessibility(int);
method public void setImportantForAutofill(int);
method public void setImportantForContentCapture(int);
+ method public void setIsCredential(boolean);
method public void setKeepScreenOn(boolean);
method public void setKeyboardNavigationCluster(boolean);
method public void setLabelFor(@IdRes int);
@@ -53785,6 +53813,7 @@
method public int getDisplayId();
method public int getId();
method public int getLayer();
+ method @NonNull public android.os.LocaleList getLocales();
method public android.view.accessibility.AccessibilityWindowInfo getParent();
method public void getRegionInScreen(@NonNull android.graphics.Region);
method public android.view.accessibility.AccessibilityNodeInfo getRoot();
@@ -54594,14 +54623,6 @@
public abstract class HandwritingGesture {
method @Nullable public final String getFallbackText();
- field public static final int GESTURE_TYPE_DELETE = 4; // 0x4
- field public static final int GESTURE_TYPE_DELETE_RANGE = 64; // 0x40
- field public static final int GESTURE_TYPE_INSERT = 2; // 0x2
- field public static final int GESTURE_TYPE_JOIN_OR_SPLIT = 16; // 0x10
- field public static final int GESTURE_TYPE_NONE = 0; // 0x0
- field public static final int GESTURE_TYPE_REMOVE_SPACE = 8; // 0x8
- field public static final int GESTURE_TYPE_SELECT = 1; // 0x1
- field public static final int GESTURE_TYPE_SELECT_RANGE = 32; // 0x20
field public static final int GRANULARITY_CHARACTER = 2; // 0x2
field public static final int GRANULARITY_WORD = 1; // 0x1
}
@@ -54824,6 +54845,7 @@
public final class InputMethodManager {
method public void dispatchKeyEventFromInputMethod(@Nullable android.view.View, @NonNull android.view.KeyEvent);
method public void displayCompletions(android.view.View, android.view.inputmethod.CompletionInfo[]);
+ method @Nullable public android.view.inputmethod.InputMethodInfo getCurrentInputMethodInfo();
method @Nullable public android.view.inputmethod.InputMethodSubtype getCurrentInputMethodSubtype();
method @NonNull public java.util.List<android.view.inputmethod.InputMethodInfo> getEnabledInputMethodList();
method @NonNull public java.util.List<android.view.inputmethod.InputMethodSubtype> getEnabledInputMethodSubtypeList(@Nullable android.view.inputmethod.InputMethodInfo, boolean);
@@ -55101,15 +55123,15 @@
public final class TextBoundsInfo implements android.os.Parcelable {
method public int describeContents();
method @IntRange(from=0, to=125) public int getCharacterBidiLevel(int);
- method @NonNull public android.graphics.RectF getCharacterBounds(int);
+ method @NonNull public void getCharacterBounds(int, @NonNull android.graphics.RectF);
method public int getCharacterFlags(int);
- method public int getEnd();
+ method public int getEndIndex();
method @NonNull public android.text.SegmentFinder getGraphemeSegmentFinder();
method @NonNull public android.text.SegmentFinder getLineSegmentFinder();
- method @NonNull public android.graphics.Matrix getMatrix();
+ method @NonNull public void getMatrix(@NonNull android.graphics.Matrix);
method public int getOffsetForPosition(float, float);
method @Nullable public int[] getRangeForRect(@NonNull android.graphics.RectF, @NonNull android.text.SegmentFinder, @NonNull android.text.Layout.TextInclusionStrategy);
- method public int getStart();
+ method public int getStartIndex();
method @NonNull public android.text.SegmentFinder getWordSegmentFinder();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.view.inputmethod.TextBoundsInfo> CREATOR;
@@ -55120,7 +55142,7 @@
}
public static final class TextBoundsInfo.Builder {
- ctor public TextBoundsInfo.Builder();
+ ctor public TextBoundsInfo.Builder(int, int);
method @NonNull public android.view.inputmethod.TextBoundsInfo build();
method @NonNull public android.view.inputmethod.TextBoundsInfo.Builder clear();
method @NonNull public android.view.inputmethod.TextBoundsInfo.Builder setCharacterBidiLevel(@NonNull int[]);
@@ -59260,6 +59282,7 @@
method public void append(CharSequence, int, int);
method public void beginBatchEdit();
method public boolean bringPointIntoView(int);
+ method public boolean bringPointIntoView(@IntRange(from=0) int, boolean);
method public void clearComposingText();
method public void debug(int);
method public boolean didTouchFocusSelect();
@@ -59297,6 +59320,8 @@
method public int getExtendedPaddingTop();
method public android.text.InputFilter[] getFilters();
method public int getFirstBaselineToTopHeight();
+ method @ColorInt public int getFocusedSearchResultHighlightColor();
+ method public int getFocusedSearchResultIndex();
method @Nullable public String getFontFeatureSettings();
method @Nullable public String getFontVariationSettings();
method public boolean getFreezesText();
@@ -59341,6 +59366,8 @@
method public android.text.TextPaint getPaint();
method public int getPaintFlags();
method public String getPrivateImeOptions();
+ method @ColorInt public int getSearchResultHighlightColor();
+ method @Nullable public int[] getSearchResultHighlights();
method public int getSelectionEnd();
method public int getSelectionStart();
method @ColorInt public int getShadowColor();
@@ -59425,6 +59452,8 @@
method public void setFallbackLineSpacing(boolean);
method public void setFilters(android.text.InputFilter[]);
method public void setFirstBaselineToTopHeight(@IntRange(from=0) @Px int);
+ method public void setFocusedSearchResultHighlightColor(@ColorInt int);
+ method public void setFocusedSearchResultIndex(int);
method public void setFontFeatureSettings(@Nullable String);
method public boolean setFontVariationSettings(@Nullable String);
method protected boolean setFrame(int, int, int, int);
@@ -59472,6 +59501,8 @@
method public void setPrivateImeOptions(String);
method public void setRawInputType(int);
method public void setScroller(android.widget.Scroller);
+ method public void setSearchResultHighlightColor(@ColorInt int);
+ method public void setSearchResultHighlights(@Nullable int...);
method public void setSelectAllOnFocus(boolean);
method public void setShadowLayer(float, float, float, int);
method public final void setShowSoftInputOnFocus(boolean);
@@ -59511,6 +59542,7 @@
method public void setWidth(int);
field public static final int AUTO_SIZE_TEXT_TYPE_NONE = 0; // 0x0
field public static final int AUTO_SIZE_TEXT_TYPE_UNIFORM = 1; // 0x1
+ field public static final int FOCUSED_SEARCH_RESULT_INDEX_NONE = -1; // 0xffffffff
}
public enum TextView.BufferType {
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index 3216bd1..55ef6de 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -82,6 +82,7 @@
}
public abstract class Context {
+ method @NonNull public android.content.Context createContextForSdkInSandbox(@NonNull android.content.pm.ApplicationInfo, int) throws android.content.pm.PackageManager.NameNotFoundException;
method @NonNull public android.os.IBinder getIApplicationThreadBinder();
method @NonNull public android.os.UserHandle getUser();
field public static final String PAC_PROXY_SERVICE = "pac_proxy";
diff --git a/core/api/removed.txt b/core/api/removed.txt
index 1fa1e89..5c4fd10 100644
--- a/core/api/removed.txt
+++ b/core/api/removed.txt
@@ -252,6 +252,34 @@
}
+package android.nfc {
+
+ public final class NfcAdapter {
+ method @Deprecated public void disableForegroundNdefPush(android.app.Activity);
+ method @Deprecated public void enableForegroundNdefPush(android.app.Activity, android.nfc.NdefMessage);
+ method @Deprecated public boolean invokeBeam(android.app.Activity);
+ method @Deprecated public boolean isNdefPushEnabled();
+ method @Deprecated public void setBeamPushUris(android.net.Uri[], android.app.Activity);
+ method @Deprecated public void setBeamPushUrisCallback(android.nfc.NfcAdapter.CreateBeamUrisCallback, android.app.Activity);
+ method @Deprecated public void setNdefPushMessage(android.nfc.NdefMessage, android.app.Activity, android.app.Activity...);
+ method @Deprecated public void setNdefPushMessageCallback(android.nfc.NfcAdapter.CreateNdefMessageCallback, android.app.Activity, android.app.Activity...);
+ method @Deprecated public void setOnNdefPushCompleteCallback(android.nfc.NfcAdapter.OnNdefPushCompleteCallback, android.app.Activity, android.app.Activity...);
+ }
+
+ @Deprecated public static interface NfcAdapter.CreateBeamUrisCallback {
+ method public android.net.Uri[] createBeamUris(android.nfc.NfcEvent);
+ }
+
+ @Deprecated public static interface NfcAdapter.CreateNdefMessageCallback {
+ method public android.nfc.NdefMessage createNdefMessage(android.nfc.NfcEvent);
+ }
+
+ @Deprecated public static interface NfcAdapter.OnNdefPushCompleteCallback {
+ method public void onNdefPushComplete(android.nfc.NfcEvent);
+ }
+
+}
+
package android.os {
public class BatteryManager {
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index ceed59f..0fce784 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -78,6 +78,7 @@
field public static final String BIND_TRANSLATION_SERVICE = "android.permission.BIND_TRANSLATION_SERVICE";
field public static final String BIND_TRUST_AGENT = "android.permission.BIND_TRUST_AGENT";
field public static final String BIND_TV_REMOTE_SERVICE = "android.permission.BIND_TV_REMOTE_SERVICE";
+ field public static final String BIND_VISUAL_QUERY_DETECTION_SERVICE = "android.permission.BIND_VISUAL_QUERY_DETECTION_SERVICE";
field public static final String BIND_WALLPAPER_EFFECTS_GENERATION_SERVICE = "android.permission.BIND_WALLPAPER_EFFECTS_GENERATION_SERVICE";
field public static final String BIND_WEARABLE_SENSING_SERVICE = "android.permission.BIND_WEARABLE_SENSING_SERVICE";
field public static final String BLUETOOTH_MAP = "android.permission.BLUETOOTH_MAP";
@@ -806,10 +807,12 @@
method @Nullable public android.content.IntentFilter getDeliveryGroupMatchingFilter();
method @Nullable public String getDeliveryGroupMatchingKey();
method public int getDeliveryGroupPolicy();
+ method public boolean isDeferUntilActive();
method public boolean isPendingIntentBackgroundActivityLaunchAllowed();
method public static android.app.BroadcastOptions makeBasic();
method @RequiresPermission(android.Manifest.permission.ACCESS_BROADCAST_RESPONSE_STATS) public void recordResponseEventWhileInBackground(@IntRange(from=0) long);
method @RequiresPermission(android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND) public void setBackgroundActivityStartsAllowed(boolean);
+ method @NonNull public android.app.BroadcastOptions setDeferUntilActive(boolean);
method @NonNull public android.app.BroadcastOptions setDeliveryGroupMatchingFilter(@NonNull android.content.IntentFilter);
method @NonNull public android.app.BroadcastOptions setDeliveryGroupMatchingKey(@NonNull String, @NonNull String);
method @NonNull public android.app.BroadcastOptions setDeliveryGroupPolicy(int);
@@ -2973,18 +2976,11 @@
}
public final class CompanionDeviceManager {
- method @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public void addOnAssociationsChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.companion.CompanionDeviceManager.OnAssociationsChangedListener);
method @RequiresPermission(android.Manifest.permission.ASSOCIATE_COMPANION_DEVICES) public void associate(@NonNull String, @NonNull android.net.MacAddress, @NonNull byte[]);
method @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public boolean canPairWithoutPrompt(@NonNull String, @NonNull String, @NonNull android.os.UserHandle);
- method @NonNull @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public java.util.List<android.companion.AssociationInfo> getAllAssociations();
method @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public boolean isDeviceAssociatedForWifiConnection(@NonNull String, @NonNull android.net.MacAddress, @NonNull android.os.UserHandle);
method @RequiresPermission(android.Manifest.permission.REQUEST_COMPANION_SELF_MANAGED) public void notifyDeviceAppeared(int);
method @RequiresPermission(android.Manifest.permission.REQUEST_COMPANION_SELF_MANAGED) public void notifyDeviceDisappeared(int);
- method @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public void removeOnAssociationsChangedListener(@NonNull android.companion.CompanionDeviceManager.OnAssociationsChangedListener);
- }
-
- public static interface CompanionDeviceManager.OnAssociationsChangedListener {
- method public void onAssociationsChanged(@NonNull java.util.List<android.companion.AssociationInfo>);
}
}
@@ -9673,18 +9669,14 @@
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean addNfcUnlockHandler(android.nfc.NfcAdapter.NfcUnlockHandler, String[]);
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean disable();
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean disable(boolean);
- method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean disableNdefPush();
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enable();
- method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableNdefPush();
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableSecureNfc(boolean);
method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean isControllerAlwaysOn();
method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean isControllerAlwaysOnSupported();
method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public void registerControllerAlwaysOnListener(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.NfcAdapter.ControllerAlwaysOnListener);
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean removeNfcUnlockHandler(android.nfc.NfcAdapter.NfcUnlockHandler);
method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean setControllerAlwaysOn(boolean);
- method public void setNdefPushMessage(android.nfc.NdefMessage, android.app.Activity, int);
method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public void unregisterControllerAlwaysOnListener(@NonNull android.nfc.NfcAdapter.ControllerAlwaysOnListener);
- field public static final int FLAG_NDEF_PUSH_NO_CONFIRM = 1; // 0x1
}
public static interface NfcAdapter.ControllerAlwaysOnListener {
@@ -10411,6 +10403,7 @@
method @RequiresPermission(anyOf={"android.permission.INTERACT_ACROSS_USERS", "android.permission.MANAGE_USERS"}) public boolean isUserVisible();
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public boolean removeUser(@NonNull android.os.UserHandle);
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public int removeUserWhenPossible(@NonNull android.os.UserHandle, boolean);
+ method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public void setBootUser(@NonNull android.os.UserHandle);
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void setUserIcon(@NonNull android.graphics.Bitmap) throws android.os.UserManager.UserOperationException;
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void setUserName(@Nullable String);
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public boolean someUserHasAccount(@NonNull String, @NonNull String);
@@ -11773,6 +11766,7 @@
method public int onEraseSubscriptions(int, @android.telephony.euicc.EuiccCardManager.ResetOption int);
method public abstract android.service.euicc.GetDefaultDownloadableSubscriptionListResult onGetDefaultDownloadableSubscriptionList(int, boolean);
method public abstract android.service.euicc.GetDownloadableSubscriptionMetadataResult onGetDownloadableSubscriptionMetadata(int, android.telephony.euicc.DownloadableSubscription, boolean);
+ method @NonNull public android.service.euicc.GetDownloadableSubscriptionMetadataResult onGetDownloadableSubscriptionMetadata(int, int, @NonNull android.telephony.euicc.DownloadableSubscription, boolean);
method public abstract String onGetEid(int);
method @NonNull public abstract android.telephony.euicc.EuiccInfo onGetEuiccInfo(int);
method @NonNull public abstract android.service.euicc.GetEuiccProfileInfoListResult onGetEuiccProfileInfoList(int);
@@ -12592,6 +12586,27 @@
public static final class VisualQueryDetectionService.Callback {
ctor public VisualQueryDetectionService.Callback();
+ method public void onAttentionGained();
+ method public void onAttentionLost();
+ method public void onQueryDetected(@NonNull String) throws java.lang.IllegalStateException;
+ method public void onQueryFinished() throws java.lang.IllegalStateException;
+ method public void onQueryRejected() throws java.lang.IllegalStateException;
+ }
+
+ public class VisualQueryDetector {
+ method public void destroy();
+ method @RequiresPermission(allOf={android.Manifest.permission.CAMERA, android.Manifest.permission.RECORD_AUDIO}) public boolean startRecognition() throws android.service.voice.HotwordDetector.IllegalDetectorStateException;
+ method @RequiresPermission(allOf={android.Manifest.permission.CAMERA, android.Manifest.permission.RECORD_AUDIO}) public boolean stopRecognition() throws android.service.voice.HotwordDetector.IllegalDetectorStateException;
+ method public void updateState(@Nullable android.os.PersistableBundle, @Nullable android.os.SharedMemory) throws android.service.voice.HotwordDetector.IllegalDetectorStateException;
+ }
+
+ public static interface VisualQueryDetector.Callback {
+ method public void onError();
+ method public void onQueryDetected(@NonNull String);
+ method public void onQueryFinished();
+ method public void onQueryRejected();
+ method public void onVisualQueryDetectionServiceInitialized(int);
+ method public void onVisualQueryDetectionServiceRestarted();
}
public class VoiceInteractionService extends android.app.Service {
@@ -12599,6 +12614,7 @@
method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_HOTWORD_DETECTION) public final android.service.voice.AlwaysOnHotwordDetector createAlwaysOnHotwordDetector(String, java.util.Locale, @Nullable android.os.PersistableBundle, @Nullable android.os.SharedMemory, android.service.voice.AlwaysOnHotwordDetector.Callback);
method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_HOTWORD_DETECTION) public final android.service.voice.HotwordDetector createHotwordDetector(@Nullable android.os.PersistableBundle, @Nullable android.os.SharedMemory, @NonNull android.service.voice.HotwordDetector.Callback);
method @NonNull @RequiresPermission("android.permission.MANAGE_VOICE_KEYPHRASES") public final android.media.voice.KeyphraseModelManager createKeyphraseModelManager();
+ method @NonNull public final android.service.voice.VisualQueryDetector createVisualQueryDetector(@Nullable android.os.PersistableBundle, @Nullable android.os.SharedMemory, @NonNull java.util.concurrent.Executor, @NonNull android.service.voice.VisualQueryDetector.Callback);
}
}
@@ -13849,6 +13865,7 @@
method @Deprecated public boolean disableCellBroadcastRange(int, int, int);
method @Deprecated public boolean enableCellBroadcastRange(int, int, int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getPremiumSmsConsent(@NonNull String);
+ method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.net.Uri getSmscIdentity();
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_CELL_BROADCASTS) public void resetAllCellBroadcastRanges();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void sendMultipartTextMessageWithoutPersisting(String, String, java.util.List<java.lang.String>, java.util.List<android.app.PendingIntent>, java.util.List<android.app.PendingIntent>);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setPremiumSmsConsent(@NonNull String, int);
@@ -15761,9 +15778,9 @@
public static interface RcsUceAdapter.CapabilitiesCallback {
method public void onCapabilitiesReceived(@NonNull java.util.List<android.telephony.ims.RcsContactUceCapability>);
- method @Deprecated public void onComplete();
+ method public default void onComplete();
method public default void onComplete(@Nullable android.telephony.ims.SipDetails);
- method @Deprecated public void onError(int, long);
+ method public default void onError(int, long);
method public default void onError(int, long, @Nullable android.telephony.ims.SipDetails);
}
@@ -16226,7 +16243,6 @@
method public void acknowledgeSms(int, @IntRange(from=0, to=65535) int, int, @NonNull byte[]);
method public void acknowledgeSmsReport(int, @IntRange(from=0, to=65535) int, int);
method public String getSmsFormat();
- method public void onMemoryAvailable(int);
method public void onReady();
method @Deprecated public final void onSendSmsResult(int, @IntRange(from=0, to=65535) int, int, int) throws java.lang.RuntimeException;
method public final void onSendSmsResultError(int, @IntRange(from=0, to=65535) int, int, int, int) throws java.lang.RuntimeException;
@@ -16535,6 +16551,7 @@
public abstract class AccessibilityDisplayProxy {
ctor public AccessibilityDisplayProxy(int, @NonNull java.util.concurrent.Executor, @NonNull java.util.List<android.accessibilityservice.AccessibilityServiceInfo>);
+ method @Nullable public android.view.accessibility.AccessibilityNodeInfo findFocus(int);
method public int getDisplayId();
method @NonNull public final java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getInstalledAndEnabledServices();
method @NonNull public java.util.List<android.view.accessibility.AccessibilityWindowInfo> getWindows();
@@ -16634,6 +16651,14 @@
}
+package android.view.inputmethod {
+
+ public final class InputMethodManager {
+ method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public android.view.inputmethod.InputMethodInfo getCurrentInputMethodInfoAsUser(@NonNull android.os.UserHandle);
+ }
+
+}
+
package android.view.translation {
public final class TranslationCapability implements android.os.Parcelable {
diff --git a/core/api/system-removed.txt b/core/api/system-removed.txt
index 2c5acf1..1c10356 100644
--- a/core/api/system-removed.txt
+++ b/core/api/system-removed.txt
@@ -140,6 +140,17 @@
}
+package android.nfc {
+
+ public final class NfcAdapter {
+ method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean disableNdefPush();
+ method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableNdefPush();
+ method public void setNdefPushMessage(android.nfc.NdefMessage, android.app.Activity, int);
+ field public static final int FLAG_NDEF_PUSH_NO_CONFIRM = 1; // 0x1
+ }
+
+}
+
package android.os {
public class Build {
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 3bc11fa..8c64e40 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -528,6 +528,7 @@
method @NonNull public static String operationSafetyReasonToString(int);
method @NonNull public static String operationToString(int);
method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public void resetDefaultCrossProfileIntentFilters(int);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void resetShouldAllowBypassingDevicePolicyManagementRoleQualificationState();
method @RequiresPermission(allOf={android.Manifest.permission.MANAGE_DEVICE_ADMINS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}) public void setActiveAdmin(@NonNull android.content.ComponentName, boolean, int);
method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public boolean setDeviceOwner(@NonNull android.content.ComponentName, int);
method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public boolean setDeviceOwnerOnly(@NonNull android.content.ComponentName, int);
@@ -897,6 +898,7 @@
method public boolean isDemo();
method public boolean isEnabled();
method public boolean isEphemeral();
+ method public boolean isForTesting();
method public boolean isFull();
method public boolean isGuest();
method public boolean isInitialized();
@@ -1246,7 +1248,7 @@
public final class CameraManager {
method public String[] getCameraIdListNoLazy() throws android.hardware.camera2.CameraAccessException;
method @RequiresPermission(allOf={android.Manifest.permission.SYSTEM_CAMERA, android.Manifest.permission.CAMERA}) public void openCamera(@NonNull String, int, @NonNull java.util.concurrent.Executor, @NonNull android.hardware.camera2.CameraDevice.StateCallback) throws android.hardware.camera2.CameraAccessException;
- field public static final long OVERRIDE_FRONT_CAMERA_APP_COMPAT = 250678880L; // 0xef10e60L
+ field public static final long OVERRIDE_CAMERA_LANDSCAPE_TO_PORTRAIT = 250678880L; // 0xef10e60L
}
public abstract static class CameraManager.AvailabilityCallback {
@@ -2025,6 +2027,7 @@
method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.content.pm.UserInfo createProfileForUser(@Nullable String, @NonNull String, int, int, @Nullable String[]);
method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.content.pm.UserInfo createRestrictedProfile(@Nullable String);
method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.content.pm.UserInfo createUser(@Nullable String, @NonNull String, int);
+ method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.os.UserHandle getBootUser();
method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public java.util.Set<java.lang.String> getPreInstallableSystemPackages(@NonNull String);
method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public String getUserType();
method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public java.util.List<android.content.pm.UserInfo> getUsers(boolean, boolean, boolean);
@@ -3206,6 +3209,17 @@
package android.view.autofill {
+ public class AutofillFeatureFlags {
+ field public static final String DEVICE_CONFIG_AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES = "compat_mode_allowed_packages";
+ field public static final String DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_ENABLED = "autofill_credential_manager_enabled";
+ field public static final String DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_IGNORE_VIEWS = "autofill_credential_manager_ignore_views";
+ field public static final String DEVICE_CONFIG_AUTOFILL_DIALOG_ENABLED = "autofill_dialog_enabled";
+ field public static final String DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES = "smart_suggestion_supported_modes";
+ field public static final String DEVICE_CONFIG_NON_AUTOFILLABLE_IME_ACTION_IDS = "non_autofillable_ime_action_ids";
+ field public static final String DEVICE_CONFIG_PACKAGE_DENYLIST_FOR_UNIMPORTANT_VIEW = "package_deny_list_for_unimportant_view";
+ field public static final String DEVICE_CONFIG_TRIGGER_FILL_REQUEST_ON_UNIMPORTANT_VIEW = "trigger_fill_request_on_unimportant_view";
+ }
+
public final class AutofillId implements android.os.Parcelable {
ctor public AutofillId(int);
ctor public AutofillId(@NonNull android.view.autofill.AutofillId, int);
@@ -3217,9 +3231,6 @@
}
public final class AutofillManager {
- field public static final String DEVICE_CONFIG_AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES = "compat_mode_allowed_packages";
- field public static final String DEVICE_CONFIG_AUTOFILL_DIALOG_ENABLED = "autofill_dialog_enabled";
- field public static final String DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES = "smart_suggestion_supported_modes";
field public static final int FLAG_SMART_SUGGESTION_OFF = 0; // 0x0
field public static final int FLAG_SMART_SUGGESTION_SYSTEM = 1; // 0x1
field public static final int MAX_TEMP_AUGMENTED_SERVICE_DURATION_MS = 120000; // 0x1d4c0
@@ -3321,7 +3332,17 @@
package android.view.inputmethod {
public abstract class HandwritingGesture {
+ method @NonNull public static android.view.inputmethod.HandwritingGesture fromByteArray(@NonNull byte[]);
method public final int getGestureType();
+ method @NonNull public final byte[] toByteArray();
+ field public static final int GESTURE_TYPE_DELETE = 4; // 0x4
+ field public static final int GESTURE_TYPE_DELETE_RANGE = 64; // 0x40
+ field public static final int GESTURE_TYPE_INSERT = 2; // 0x2
+ field public static final int GESTURE_TYPE_JOIN_OR_SPLIT = 16; // 0x10
+ field public static final int GESTURE_TYPE_NONE = 0; // 0x0
+ field public static final int GESTURE_TYPE_REMOVE_SPACE = 8; // 0x8
+ field public static final int GESTURE_TYPE_SELECT = 1; // 0x1
+ field public static final int GESTURE_TYPE_SELECT_RANGE = 32; // 0x20
}
public final class InlineSuggestion implements android.os.Parcelable {
@@ -3662,6 +3683,7 @@
public final class WindowContainerTransaction implements android.os.Parcelable {
ctor public WindowContainerTransaction();
+ method @NonNull public android.window.WindowContainerTransaction clearAdjacentTaskFragments(@NonNull android.os.IBinder);
method @NonNull public android.window.WindowContainerTransaction clearLaunchAdjacentFlagRoot(@NonNull android.window.WindowContainerToken);
method @NonNull public android.window.WindowContainerTransaction createTaskFragment(@NonNull android.window.TaskFragmentCreationParams);
method @NonNull public android.window.WindowContainerTransaction deleteTaskFragment(@NonNull android.os.IBinder);
@@ -3676,7 +3698,7 @@
method @NonNull public android.window.WindowContainerTransaction scheduleFinishEnterPip(@NonNull android.window.WindowContainerToken, @NonNull android.graphics.Rect);
method @NonNull public android.window.WindowContainerTransaction setActivityWindowingMode(@NonNull android.window.WindowContainerToken, int);
method @NonNull public android.window.WindowContainerTransaction setAdjacentRoots(@NonNull android.window.WindowContainerToken, @NonNull android.window.WindowContainerToken);
- method @NonNull public android.window.WindowContainerTransaction setAdjacentTaskFragments(@NonNull android.os.IBinder, @Nullable android.os.IBinder, @Nullable android.window.WindowContainerTransaction.TaskFragmentAdjacentParams);
+ method @NonNull public android.window.WindowContainerTransaction setAdjacentTaskFragments(@NonNull android.os.IBinder, @NonNull android.os.IBinder, @Nullable android.window.WindowContainerTransaction.TaskFragmentAdjacentParams);
method @NonNull public android.window.WindowContainerTransaction setAppBounds(@NonNull android.window.WindowContainerToken, @NonNull android.graphics.Rect);
method @NonNull public android.window.WindowContainerTransaction setBounds(@NonNull android.window.WindowContainerToken, @NonNull android.graphics.Rect);
method @NonNull public android.window.WindowContainerTransaction setBoundsChangeTransaction(@NonNull android.window.WindowContainerToken, @NonNull android.view.SurfaceControl.Transaction);
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index dbdee07..821a23c 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -16,6 +16,8 @@
package android.accounts;
+import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
+
import android.annotation.BroadcastBehavior;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -891,15 +893,24 @@
* @return An {@link AccountManagerFuture} which resolves to a Boolean, true if the account
* exists and has all of the specified features.
*/
+ @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE,
+ requiresPermissionIfNotCaller = INTERACT_ACROSS_USERS_FULL)
public AccountManagerFuture<Boolean> hasFeatures(final Account account,
final String[] features,
AccountManagerCallback<Boolean> callback, Handler handler) {
+ return hasFeaturesAsUser(account, features, callback, handler, mContext.getUserId());
+ }
+
+ private AccountManagerFuture<Boolean> hasFeaturesAsUser(
+ final Account account, final String[] features,
+ AccountManagerCallback<Boolean> callback, Handler handler, int userId) {
if (account == null) throw new IllegalArgumentException("account is null");
if (features == null) throw new IllegalArgumentException("features is null");
return new Future2Task<Boolean>(handler, callback) {
@Override
public void doWork() throws RemoteException {
- mService.hasFeatures(mResponse, account, features, mContext.getOpPackageName());
+ mService.hasFeatures(
+ mResponse, account, features, userId, mContext.getOpPackageName());
}
@Override
public Boolean bundleToResult(Bundle bundle) throws AuthenticatorException {
@@ -3319,7 +3330,7 @@
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
+ @RequiresPermission(INTERACT_ACROSS_USERS_FULL)
public AccountManagerFuture<Bundle> finishSessionAsUser(
final Bundle sessionBundle,
final Activity activity,
diff --git a/core/java/android/accounts/IAccountManager.aidl b/core/java/android/accounts/IAccountManager.aidl
index a3a7b0c..08fb308 100644
--- a/core/java/android/accounts/IAccountManager.aidl
+++ b/core/java/android/accounts/IAccountManager.aidl
@@ -38,7 +38,7 @@
Account[] getAccountsByTypeForPackage(String type, String packageName, String opPackageName);
Account[] getAccountsAsUser(String accountType, int userId, String opPackageName);
void hasFeatures(in IAccountManagerResponse response, in Account account, in String[] features,
- String opPackageName);
+ int userId, String opPackageName);
void getAccountByTypeAndFeatures(in IAccountManagerResponse response, String accountType,
in String[] features, String opPackageName);
void getAccountsByFeatures(in IAccountManagerResponse response, String accountType,
diff --git a/core/java/android/animation/Animator.java b/core/java/android/animation/Animator.java
index a81ef18..a9d14df 100644
--- a/core/java/android/animation/Animator.java
+++ b/core/java/android/animation/Animator.java
@@ -23,7 +23,6 @@
import android.content.pm.ActivityInfo.Config;
import android.content.res.ConstantState;
import android.os.Build;
-import android.util.LongArray;
import java.util.ArrayList;
@@ -547,6 +546,7 @@
*/
void skipToEndValue(boolean inReverse) {}
+
/**
* Internal use only.
*
@@ -559,36 +559,9 @@
}
/**
- * Internal use only. Changes the value of the animator as if currentPlayTime has passed since
- * the start of the animation. Therefore, currentPlayTime includes the start delay, and any
- * repetition. lastPlayTime is similar and is used to calculate how many repeats have been
- * done between the two times.
+ * Internal use only.
*/
- void animateValuesInRange(long currentPlayTime, long lastPlayTime, boolean notify) {}
-
- /**
- * Internal use only. This animates any animation that has ended since lastPlayTime.
- * If an animation hasn't been finished, no change will be made.
- */
- void animateSkipToEnds(long currentPlayTime, long lastPlayTime, boolean notify) {}
-
- /**
- * Internal use only. Adds all start times (after delay) to and end times to times.
- * The value must include offset.
- */
- void getStartAndEndTimes(LongArray times, long offset) {
- long startTime = offset + getStartDelay();
- if (times.indexOf(startTime) < 0) {
- times.add(startTime);
- }
- long duration = getTotalDuration();
- if (duration != DURATION_INFINITE) {
- long endTime = duration + offset;
- if (times.indexOf(endTime) < 0) {
- times.add(endTime);
- }
- }
- }
+ void animateBasedOnPlayTime(long currentPlayTime, long lastPlayTime, boolean inReverse) {}
/**
* <p>An animation listener receives notifications from an animation.
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index 257adfe..bc8db02 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -23,11 +23,9 @@
import android.util.AndroidRuntimeException;
import android.util.ArrayMap;
import android.util.Log;
-import android.util.LongArray;
import android.view.animation.Animation;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
@@ -183,16 +181,6 @@
*/
private long mPauseTime = -1;
- /**
- * The start and stop times of all descendant animators.
- */
- private long[] mChildStartAndStopTimes;
-
- /**
- * Tracks whether we've notified listeners of the onAnimationStart() event.
- */
- private boolean mStartListenersCalled;
-
// This is to work around a bug in b/34736819. This needs to be removed once app team
// fixes their side.
private AnimatorListenerAdapter mAnimationEndListener = new AnimatorListenerAdapter() {
@@ -741,7 +729,14 @@
startAnimation();
}
- notifyStartListeners(inReverse);
+ if (mListeners != null) {
+ ArrayList<AnimatorListener> tmpListeners =
+ (ArrayList<AnimatorListener>) mListeners.clone();
+ int numListeners = tmpListeners.size();
+ for (int i = 0; i < numListeners; ++i) {
+ tmpListeners.get(i).onAnimationStart(this, inReverse);
+ }
+ }
if (isEmptySet) {
// In the case of empty AnimatorSet, or 0 duration scale, we will trigger the
// onAnimationEnd() right away.
@@ -749,32 +744,6 @@
}
}
- private void notifyStartListeners(boolean inReverse) {
- if (mListeners != null && !mStartListenersCalled) {
- ArrayList<AnimatorListener> tmpListeners =
- (ArrayList<AnimatorListener>) mListeners.clone();
- int numListeners = tmpListeners.size();
- for (int i = 0; i < numListeners; ++i) {
- AnimatorListener listener = tmpListeners.get(i);
- listener.onAnimationStart(this, inReverse);
- }
- }
- mStartListenersCalled = true;
- }
-
- private void notifyEndListeners(boolean inReverse) {
- if (mListeners != null && mStartListenersCalled) {
- ArrayList<AnimatorListener> tmpListeners =
- (ArrayList<AnimatorListener>) mListeners.clone();
- int numListeners = tmpListeners.size();
- for (int i = 0; i < numListeners; ++i) {
- AnimatorListener listener = tmpListeners.get(i);
- listener.onAnimationEnd(this, inReverse);
- }
- }
- mStartListenersCalled = false;
- }
-
// Returns true if set is empty or contains nothing but animator sets with no start delay.
private static boolean isEmptySet(AnimatorSet set) {
if (set.getStartDelay() > 0) {
@@ -810,25 +779,26 @@
@Override
void skipToEndValue(boolean inReverse) {
+ if (!isInitialized()) {
+ throw new UnsupportedOperationException("Children must be initialized.");
+ }
+
// This makes sure the animation events are sorted an up to date.
initAnimation();
- initChildren();
// Calling skip to the end in the sequence that they would be called in a forward/reverse
// run, such that the sequential animations modifying the same property would have
// the right value in the end.
if (inReverse) {
for (int i = mEvents.size() - 1; i >= 0; i--) {
- AnimationEvent event = mEvents.get(i);
- if (event.mEvent == AnimationEvent.ANIMATION_DELAY_ENDED) {
- event.mNode.mAnimation.skipToEndValue(true);
+ if (mEvents.get(i).mEvent == AnimationEvent.ANIMATION_DELAY_ENDED) {
+ mEvents.get(i).mNode.mAnimation.skipToEndValue(true);
}
}
} else {
for (int i = 0; i < mEvents.size(); i++) {
- AnimationEvent event = mEvents.get(i);
- if (event.mEvent == AnimationEvent.ANIMATION_END) {
- event.mNode.mAnimation.skipToEndValue(false);
+ if (mEvents.get(i).mEvent == AnimationEvent.ANIMATION_END) {
+ mEvents.get(i).mNode.mAnimation.skipToEndValue(false);
}
}
}
@@ -844,216 +814,72 @@
* {@link android.view.animation.Animation.AnimationListener#onAnimationRepeat(Animation)},
* as needed, based on the last play time and current play time.
*/
- private void animateBasedOnPlayTime(
- long currentPlayTime,
- long lastPlayTime,
- boolean inReverse,
- boolean notify
- ) {
- if (currentPlayTime < 0 || lastPlayTime < -1) {
+ @Override
+ void animateBasedOnPlayTime(long currentPlayTime, long lastPlayTime, boolean inReverse) {
+ if (currentPlayTime < 0 || lastPlayTime < 0) {
throw new UnsupportedOperationException("Error: Play time should never be negative.");
}
// TODO: take into account repeat counts and repeat callback when repeat is implemented.
+ // Clamp currentPlayTime and lastPlayTime
+ // TODO: Make this more efficient
+
+ // Convert the play times to the forward direction.
if (inReverse) {
- long duration = getTotalDuration();
- if (duration == DURATION_INFINITE) {
- throw new UnsupportedOperationException(
- "Cannot reverse AnimatorSet with infinite duration"
- );
+ if (getTotalDuration() == DURATION_INFINITE) {
+ throw new UnsupportedOperationException("Cannot reverse AnimatorSet with infinite"
+ + " duration");
}
- // Convert the play times to the forward direction.
+ long duration = getTotalDuration() - mStartDelay;
currentPlayTime = Math.min(currentPlayTime, duration);
currentPlayTime = duration - currentPlayTime;
lastPlayTime = duration - lastPlayTime;
+ inReverse = false;
}
- long[] startEndTimes = ensureChildStartAndEndTimes();
- int index = findNextIndex(lastPlayTime, startEndTimes);
- int endIndex = findNextIndex(currentPlayTime, startEndTimes);
-
- // Change values at the start/end times so that values are set in the right order.
- // We don't want an animator that would finish before another to override the value
- // set by another animator that finishes earlier.
- if (currentPlayTime >= lastPlayTime) {
- while (index < endIndex) {
- long playTime = startEndTimes[index];
- if (lastPlayTime != playTime) {
- animateSkipToEnds(playTime, lastPlayTime, notify);
- animateValuesInRange(playTime, lastPlayTime, notify);
- lastPlayTime = playTime;
- }
- index++;
- }
- } else {
- while (index > endIndex) {
- index--;
- long playTime = startEndTimes[index];
- if (lastPlayTime != playTime) {
- animateSkipToEnds(playTime, lastPlayTime, notify);
- animateValuesInRange(playTime, lastPlayTime, notify);
- lastPlayTime = playTime;
- }
- }
- }
- if (currentPlayTime != lastPlayTime) {
- animateSkipToEnds(currentPlayTime, lastPlayTime, notify);
- animateValuesInRange(currentPlayTime, lastPlayTime, notify);
- }
- }
-
- /**
- * Looks through startEndTimes for playTime. If it is in startEndTimes, the index after
- * is returned. Otherwise, it returns the index at which it would be placed if it were
- * to be inserted.
- */
- private int findNextIndex(long playTime, long[] startEndTimes) {
- int index = Arrays.binarySearch(startEndTimes, playTime);
- if (index < 0) {
- index = -index - 1;
- } else {
- index++;
- }
- return index;
- }
-
- @Override
- void animateSkipToEnds(long currentPlayTime, long lastPlayTime, boolean notify) {
- initAnimation();
-
- if (lastPlayTime > currentPlayTime) {
- if (notify) {
- notifyStartListeners(true);
- }
- for (int i = mEvents.size() - 1; i >= 0; i--) {
- AnimationEvent event = mEvents.get(i);
- Node node = event.mNode;
- if (event.mEvent == AnimationEvent.ANIMATION_END
- && node.mStartTime != DURATION_INFINITE
- ) {
- Animator animator = node.mAnimation;
- long start = node.mStartTime;
- long end = node.mTotalDuration == DURATION_INFINITE
- ? Long.MAX_VALUE : node.mEndTime;
- if (currentPlayTime <= start && start < lastPlayTime) {
- animator.animateSkipToEnds(
- 0,
- lastPlayTime - node.mStartTime,
- notify
- );
- } else if (start <= currentPlayTime && currentPlayTime <= end) {
- animator.animateSkipToEnds(
- currentPlayTime - node.mStartTime,
- lastPlayTime - node.mStartTime,
- notify
- );
- }
- }
- }
- if (currentPlayTime <= 0 && notify) {
- notifyEndListeners(true);
- }
- } else {
- if (notify) {
- notifyStartListeners(false);
- }
- int eventsSize = mEvents.size();
- for (int i = 0; i < eventsSize; i++) {
- AnimationEvent event = mEvents.get(i);
- Node node = event.mNode;
- if (event.mEvent == AnimationEvent.ANIMATION_DELAY_ENDED
- && node.mStartTime != DURATION_INFINITE
- ) {
- Animator animator = node.mAnimation;
- long start = node.mStartTime;
- long end = node.mTotalDuration == DURATION_INFINITE
- ? Long.MAX_VALUE : node.mEndTime;
- if (lastPlayTime < end && end <= currentPlayTime) {
- animator.animateSkipToEnds(
- end - node.mStartTime,
- lastPlayTime - node.mStartTime,
- notify
- );
- } else if (start <= currentPlayTime && currentPlayTime <= end) {
- animator.animateSkipToEnds(
- currentPlayTime - node.mStartTime,
- lastPlayTime - node.mStartTime,
- notify
- );
- }
- }
- }
- if (currentPlayTime >= getTotalDuration() && notify) {
- notifyEndListeners(false);
- }
- }
- }
-
- @Override
- void animateValuesInRange(long currentPlayTime, long lastPlayTime, boolean notify) {
- initAnimation();
-
- if (notify) {
- if (lastPlayTime < 0 || (lastPlayTime == 0 && currentPlayTime > 0)) {
- notifyStartListeners(false);
- } else {
- long duration = getTotalDuration();
- if (duration >= 0
- && (lastPlayTime > duration || (lastPlayTime == duration
- && currentPlayTime < duration))
- ) {
- notifyStartListeners(true);
- }
- }
- }
-
- int eventsSize = mEvents.size();
- for (int i = 0; i < eventsSize; i++) {
+ ArrayList<Node> unfinishedNodes = new ArrayList<>();
+ // Assumes forward playing from here on.
+ for (int i = 0; i < mEvents.size(); i++) {
AnimationEvent event = mEvents.get(i);
- Node node = event.mNode;
- if (event.mEvent == AnimationEvent.ANIMATION_DELAY_ENDED
- && node.mStartTime != DURATION_INFINITE
- ) {
- Animator animator = node.mAnimation;
- long start = node.mStartTime;
- long end = node.mTotalDuration == DURATION_INFINITE
- ? Long.MAX_VALUE : node.mEndTime;
- if ((start < currentPlayTime && currentPlayTime < end)
- || (start == currentPlayTime && lastPlayTime < start)
- || (end == currentPlayTime && lastPlayTime > end)
- ) {
- animator.animateValuesInRange(
- currentPlayTime - node.mStartTime,
- Math.max(-1, lastPlayTime - node.mStartTime),
- notify
- );
+ if (event.getTime() > currentPlayTime || event.getTime() == DURATION_INFINITE) {
+ break;
+ }
+
+ // This animation started prior to the current play time, and won't finish before the
+ // play time, add to the unfinished list.
+ if (event.mEvent == AnimationEvent.ANIMATION_DELAY_ENDED) {
+ if (event.mNode.mEndTime == DURATION_INFINITE
+ || event.mNode.mEndTime > currentPlayTime) {
+ unfinishedNodes.add(event.mNode);
}
}
- }
- }
-
- private long[] ensureChildStartAndEndTimes() {
- if (mChildStartAndStopTimes == null) {
- LongArray startAndEndTimes = new LongArray();
- getStartAndEndTimes(startAndEndTimes, 0);
- long[] times = startAndEndTimes.toArray();
- Arrays.sort(times);
- mChildStartAndStopTimes = times;
- }
- return mChildStartAndStopTimes;
- }
-
- @Override
- void getStartAndEndTimes(LongArray times, long offset) {
- int eventsSize = mEvents.size();
- for (int i = 0; i < eventsSize; i++) {
- AnimationEvent event = mEvents.get(i);
- if (event.mEvent == AnimationEvent.ANIMATION_DELAY_ENDED
- && event.mNode.mStartTime != DURATION_INFINITE
- ) {
- event.mNode.mAnimation.getStartAndEndTimes(times, offset + event.mNode.mStartTime);
+ // For animations that do finish before the play time, end them in the sequence that
+ // they would in a normal run.
+ if (event.mEvent == AnimationEvent.ANIMATION_END) {
+ // Skip to the end of the animation.
+ event.mNode.mAnimation.skipToEndValue(false);
}
}
+
+ // Seek unfinished animation to the right time.
+ for (int i = 0; i < unfinishedNodes.size(); i++) {
+ Node node = unfinishedNodes.get(i);
+ long playTime = getPlayTimeForNode(currentPlayTime, node, inReverse);
+ if (!inReverse) {
+ playTime -= node.mAnimation.getStartDelay();
+ }
+ node.mAnimation.animateBasedOnPlayTime(playTime, lastPlayTime, inReverse);
+ }
+
+ // Seek not yet started animations.
+ for (int i = 0; i < mEvents.size(); i++) {
+ AnimationEvent event = mEvents.get(i);
+ if (event.getTime() > currentPlayTime
+ && event.mEvent == AnimationEvent.ANIMATION_DELAY_ENDED) {
+ event.mNode.mAnimation.skipToEndValue(true);
+ }
+ }
+
}
@Override
@@ -1073,6 +899,10 @@
return mChildrenInitialized;
}
+ private void skipToStartValue(boolean inReverse) {
+ skipToEndValue(!inReverse);
+ }
+
/**
* Sets the position of the animation to the specified point in time. This time should
* be between 0 and the total duration of the animation, including any repetition. If
@@ -1080,11 +910,6 @@
* set to this time; it will simply set the time to this value and perform any appropriate
* actions based on that time. If the animation is already running, then setCurrentPlayTime()
* will set the current playing time to this value and continue playing from that point.
- * On {@link Build.VERSION_CODES#UPSIDE_DOWN_CAKE} and above, an AnimatorSet
- * that hasn't been {@link #start()}ed, will issue
- * {@link android.animation.Animator.AnimatorListener#onAnimationStart(Animator, boolean)}
- * and {@link android.animation.Animator.AnimatorListener#onAnimationEnd(Animator, boolean)}
- * events.
*
* @param playTime The time, in milliseconds, to which the animation is advanced or rewound.
* Unless the animation is reversing, the playtime is considered the time since
@@ -1101,27 +926,29 @@
if ((getTotalDuration() != DURATION_INFINITE && playTime > getTotalDuration() - mStartDelay)
|| playTime < 0) {
throw new UnsupportedOperationException("Error: Play time should always be in between"
- + " 0 and duration.");
+ + "0 and duration.");
}
initAnimation();
- long lastPlayTime = mSeekState.getPlayTime();
if (!isStarted() || isPaused()) {
- if (mReversing && !isStarted()) {
+ if (mReversing) {
throw new UnsupportedOperationException("Error: Something went wrong. mReversing"
+ " should not be set when AnimatorSet is not started.");
}
if (!mSeekState.isActive()) {
findLatestEventIdForTime(0);
- initChildren();
// Set all the values to start values.
- skipToEndValue(!mReversing);
+ initChildren();
mSeekState.setPlayTime(0, mReversing);
}
+ animateBasedOnPlayTime(playTime, 0, mReversing);
+ mSeekState.setPlayTime(playTime, mReversing);
+ } else {
+ // If the animation is running, just set the seek time and wait until the next frame
+ // (i.e. doAnimationFrame(...)) to advance the animation.
+ mSeekState.setPlayTime(playTime, mReversing);
}
- animateBasedOnPlayTime(playTime, lastPlayTime, mReversing, true);
- mSeekState.setPlayTime(playTime, mReversing);
}
/**
@@ -1154,16 +981,10 @@
private void initChildren() {
if (!isInitialized()) {
mChildrenInitialized = true;
-
- // We have to initialize all the start values so that they are based on the previous
- // values.
- long[] times = ensureChildStartAndEndTimes();
-
- long previousTime = -1;
- for (long time : times) {
- animateBasedOnPlayTime(time, previousTime, false, false);
- previousTime = time;
- }
+ // Forcefully initialize all children based on their end time, so that if the start
+ // value of a child is dependent on a previous animation, the animation will be
+ // initialized after the the previous animations have been advanced to the end.
+ skipToEndValue(false);
}
}
@@ -1237,7 +1058,7 @@
for (int i = 0; i < mPlayingSet.size(); i++) {
Node node = mPlayingSet.get(i);
if (!node.mEnded) {
- pulseFrame(node, getPlayTimeForNodeIncludingDelay(unscaledPlayTime, node));
+ pulseFrame(node, getPlayTimeForNode(unscaledPlayTime, node));
}
}
@@ -1308,7 +1129,7 @@
pulseFrame(node, 0);
} else if (event.mEvent == AnimationEvent.ANIMATION_DELAY_ENDED && !node.mEnded) {
// end event:
- pulseFrame(node, getPlayTimeForNodeIncludingDelay(playTime, node));
+ pulseFrame(node, getPlayTimeForNode(playTime, node));
}
}
} else {
@@ -1329,7 +1150,7 @@
pulseFrame(node, 0);
} else if (event.mEvent == AnimationEvent.ANIMATION_END && !node.mEnded) {
// start event:
- pulseFrame(node, getPlayTimeForNodeIncludingDelay(playTime, node));
+ pulseFrame(node, getPlayTimeForNode(playTime, node));
}
}
}
@@ -1351,15 +1172,11 @@
}
}
- private long getPlayTimeForNodeIncludingDelay(long overallPlayTime, Node node) {
- return getPlayTimeForNodeIncludingDelay(overallPlayTime, node, mReversing);
+ private long getPlayTimeForNode(long overallPlayTime, Node node) {
+ return getPlayTimeForNode(overallPlayTime, node, mReversing);
}
- private long getPlayTimeForNodeIncludingDelay(
- long overallPlayTime,
- Node node,
- boolean inReverse
- ) {
+ private long getPlayTimeForNode(long overallPlayTime, Node node, boolean inReverse) {
if (inReverse) {
overallPlayTime = getTotalDuration() - overallPlayTime;
return node.mEndTime - overallPlayTime;
@@ -1381,8 +1198,26 @@
}
// Set the child animators to the right end:
if (mShouldResetValuesAtStart) {
- initChildren();
- skipToEndValue(!mReversing);
+ if (isInitialized()) {
+ skipToEndValue(!mReversing);
+ } else if (mReversing) {
+ // Reversing but haven't initialized all the children yet.
+ initChildren();
+ skipToEndValue(!mReversing);
+ } else {
+ // If not all children are initialized and play direction is forward
+ for (int i = mEvents.size() - 1; i >= 0; i--) {
+ if (mEvents.get(i).mEvent == AnimationEvent.ANIMATION_DELAY_ENDED) {
+ Animator anim = mEvents.get(i).mNode.mAnimation;
+ // Only reset the animations that have been initialized to start value,
+ // so that if they are defined without a start value, they will get the
+ // values set at the right time (i.e. the next animation run)
+ if (anim.isInitialized()) {
+ anim.skipToEndValue(true);
+ }
+ }
+ }
+ }
}
if (mReversing || mStartDelay == 0 || mSeekState.isActive()) {
@@ -1457,7 +1292,15 @@
// No longer receive callbacks
removeAnimationCallback();
- notifyEndListeners(mReversing);
+ // Call end listener
+ if (mListeners != null) {
+ ArrayList<AnimatorListener> tmpListeners =
+ (ArrayList<AnimatorListener>) mListeners.clone();
+ int numListeners = tmpListeners.size();
+ for (int i = 0; i < numListeners; ++i) {
+ tmpListeners.get(i).onAnimationEnd(this, mReversing);
+ }
+ }
removeAnimationEndListener();
mSelfPulse = true;
mReversing = false;
@@ -2079,11 +1922,11 @@
}
void setPlayTime(long playTime, boolean inReverse) {
+ // TODO: This can be simplified.
+
// Clamp the play time
if (getTotalDuration() != DURATION_INFINITE) {
mPlayTime = Math.min(playTime, getTotalDuration() - mStartDelay);
- } else {
- mPlayTime = playTime;
}
mPlayTime = Math.max(0, mPlayTime);
mSeekingInReverse = inReverse;
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 7009725..6ab7ae6 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -324,9 +324,8 @@
listenerCopy = new ArrayList<>(sDurationScaleChangeListeners);
}
- int listenersSize = listenerCopy.size();
- for (int i = 0; i < listenersSize; i++) {
- final DurationScaleChangeListener listener = listenerCopy.get(i).get();
+ for (WeakReference<DurationScaleChangeListener> listenerRef : listenerCopy) {
+ final DurationScaleChangeListener listener = listenerRef.get();
if (listener != null) {
listener.onChanged(durationScale);
}
@@ -625,7 +624,7 @@
public void setValues(PropertyValuesHolder... values) {
int numValues = values.length;
mValues = values;
- mValuesMap = new HashMap<>(numValues);
+ mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues);
for (int i = 0; i < numValues; ++i) {
PropertyValuesHolder valuesHolder = values[i];
mValuesMap.put(valuesHolder.getPropertyName(), valuesHolder);
@@ -659,11 +658,9 @@
@CallSuper
void initAnimation() {
if (!mInitialized) {
- if (mValues != null) {
- int numValues = mValues.length;
- for (int i = 0; i < numValues; ++i) {
- mValues[i].init();
- }
+ int numValues = mValues.length;
+ for (int i = 0; i < numValues; ++i) {
+ mValues[i].init();
}
mInitialized = true;
}
@@ -1108,30 +1105,18 @@
}
}
- private void notifyStartListeners(boolean isReversing) {
+ private void notifyStartListeners() {
if (mListeners != null && !mStartListenersCalled) {
ArrayList<AnimatorListener> tmpListeners =
(ArrayList<AnimatorListener>) mListeners.clone();
int numListeners = tmpListeners.size();
for (int i = 0; i < numListeners; ++i) {
- tmpListeners.get(i).onAnimationStart(this, isReversing);
+ tmpListeners.get(i).onAnimationStart(this, mReversing);
}
}
mStartListenersCalled = true;
}
- private void notifyEndListeners(boolean isReversing) {
- if (mListeners != null && mStartListenersCalled) {
- ArrayList<AnimatorListener> tmpListeners =
- (ArrayList<AnimatorListener>) mListeners.clone();
- int numListeners = tmpListeners.size();
- for (int i = 0; i < numListeners; ++i) {
- tmpListeners.get(i).onAnimationEnd(this, isReversing);
- }
- }
- mStartListenersCalled = false;
- }
-
/**
* Start the animation playing. This version of start() takes a boolean flag that indicates
* whether the animation should play in reverse. The flag is usually false, but may be set
@@ -1222,16 +1207,12 @@
if ((mStarted || mRunning) && mListeners != null) {
if (!mRunning) {
// If it's not yet running, then start listeners weren't called. Call them now.
- notifyStartListeners(mReversing);
+ notifyStartListeners();
}
- int listenersSize = mListeners.size();
- if (listenersSize > 0) {
- ArrayList<AnimatorListener> tmpListeners =
- (ArrayList<AnimatorListener>) mListeners.clone();
- for (int i = 0; i < listenersSize; i++) {
- AnimatorListener listener = tmpListeners.get(i);
- listener.onAnimationCancel(this);
- }
+ ArrayList<AnimatorListener> tmpListeners =
+ (ArrayList<AnimatorListener>) mListeners.clone();
+ for (AnimatorListener listener : tmpListeners) {
+ listener.onAnimationCancel(this);
}
}
endAnimation();
@@ -1336,14 +1317,22 @@
boolean notify = (mStarted || mRunning) && mListeners != null;
if (notify && !mRunning) {
// If it's not yet running, then start listeners weren't called. Call them now.
- notifyStartListeners(mReversing);
+ notifyStartListeners();
}
mRunning = false;
mStarted = false;
+ mStartListenersCalled = false;
mLastFrameTime = -1;
mFirstFrameTime = -1;
mStartTime = -1;
- notifyEndListeners(mReversing);
+ if (notify && mListeners != null) {
+ ArrayList<AnimatorListener> tmpListeners =
+ (ArrayList<AnimatorListener>) mListeners.clone();
+ int numListeners = tmpListeners.size();
+ for (int i = 0; i < numListeners; ++i) {
+ tmpListeners.get(i).onAnimationEnd(this, mReversing);
+ }
+ }
// mReversing needs to be reset *after* notifying the listeners for the end callbacks.
mReversing = false;
if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
@@ -1370,8 +1359,9 @@
} else {
mOverallFraction = 0f;
}
-
- notifyStartListeners(mReversing);
+ if (mListeners != null) {
+ notifyStartListeners();
+ }
}
/**
@@ -1462,32 +1452,16 @@
* will be called.
*/
@Override
- void animateValuesInRange(long currentPlayTime, long lastPlayTime, boolean notify) {
- if (currentPlayTime < 0 || lastPlayTime < -1) {
+ void animateBasedOnPlayTime(long currentPlayTime, long lastPlayTime, boolean inReverse) {
+ if (currentPlayTime < 0 || lastPlayTime < 0) {
throw new UnsupportedOperationException("Error: Play time should never be negative.");
}
initAnimation();
- long duration = getTotalDuration();
- if (notify) {
- if (lastPlayTime < 0 || (lastPlayTime == 0 && currentPlayTime > 0)) {
- notifyStartListeners(false);
- } else if (lastPlayTime > duration
- || (lastPlayTime == duration && currentPlayTime < duration)
- ) {
- notifyStartListeners(true);
- }
- }
- if (duration >= 0) {
- lastPlayTime = Math.min(duration, lastPlayTime);
- }
- lastPlayTime -= mStartDelay;
- currentPlayTime -= mStartDelay;
-
// Check whether repeat callback is needed only when repeat count is non-zero
if (mRepeatCount > 0) {
- int iteration = Math.max(0, (int) (currentPlayTime / mDuration));
- int lastIteration = Math.max(0, (int) (lastPlayTime / mDuration));
+ int iteration = (int) (currentPlayTime / mDuration);
+ int lastIteration = (int) (lastPlayTime / mDuration);
// Clamp iteration to [0, mRepeatCount]
iteration = Math.min(iteration, mRepeatCount);
@@ -1503,37 +1477,16 @@
}
}
- if (mRepeatCount != INFINITE && currentPlayTime > (mRepeatCount + 1) * mDuration) {
- throw new IllegalStateException("Can't animate a value outside of the duration");
+ if (mRepeatCount != INFINITE && currentPlayTime >= (mRepeatCount + 1) * mDuration) {
+ skipToEndValue(inReverse);
} else {
// Find the current fraction:
- float fraction = Math.max(0, currentPlayTime) / (float) mDuration;
- fraction = getCurrentIterationFraction(fraction, false);
+ float fraction = currentPlayTime / (float) mDuration;
+ fraction = getCurrentIterationFraction(fraction, inReverse);
animateValue(fraction);
}
}
- @Override
- void animateSkipToEnds(long currentPlayTime, long lastPlayTime, boolean notify) {
- boolean inReverse = currentPlayTime < lastPlayTime;
- boolean doSkip;
- if (currentPlayTime <= 0 && lastPlayTime > 0) {
- doSkip = true;
- } else {
- long duration = getTotalDuration();
- doSkip = duration >= 0 && currentPlayTime >= duration && lastPlayTime < duration;
- }
- if (doSkip) {
- if (notify) {
- notifyStartListeners(inReverse);
- }
- skipToEndValue(inReverse);
- if (notify) {
- notifyEndListeners(inReverse);
- }
- }
- }
-
/**
* Internal use only.
* Skips the animation value to end/start, depending on whether the play direction is forward
@@ -1688,9 +1641,6 @@
Trace.traceCounter(Trace.TRACE_TAG_VIEW, getNameForTrace() + hashCode(),
(int) (fraction * 1000));
}
- if (mValues == null) {
- return;
- }
fraction = mInterpolator.getInterpolation(fraction);
mCurrentFraction = fraction;
int numValues = mValues.length;
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 174c982..b626493 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -404,6 +404,13 @@
public static final int START_FLAG_NATIVE_DEBUGGING = 1<<3;
/**
+ * Flag for IActivityManaqer.startActivity: launch the app for
+ * debugging and suspend threads.
+ * @hide
+ */
+ public static final int START_FLAG_DEBUG_SUSPEND = 1 << 4;
+
+ /**
* Result for IActivityManaqer.broadcastIntent: success!
* @hide
*/
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 6826b67..a381fea 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -20,6 +20,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.PermissionMethod;
+import android.annotation.PermissionName;
import android.annotation.UserIdInt;
import android.app.ActivityManager.ProcessCapability;
import android.app.ActivityManager.RestrictionLevel;
@@ -28,11 +30,10 @@
import android.content.IIntentReceiver;
import android.content.IIntentSender;
import android.content.Intent;
+import android.content.ServiceConnection;
import android.content.pm.ActivityInfo;
import android.content.pm.ActivityPresentationInfo;
import android.content.pm.ApplicationInfo;
-import android.content.pm.PermissionMethod;
-import android.content.pm.PermissionName;
import android.content.pm.UserInfo;
import android.net.Uri;
import android.os.Bundle;
@@ -922,4 +923,30 @@
* @param callingPid The PID mapped with the callback.
*/
public abstract void unregisterStrictModeCallback(int callingPid);
+
+ /**
+ * Start a foreground service delegate.
+ * @param options foreground service delegate options.
+ * @param connection a service connection served as callback to caller.
+ * @return true if delegate is started successfully, false otherwise.
+ * @hide
+ */
+ public abstract boolean startForegroundServiceDelegate(
+ @NonNull ForegroundServiceDelegationOptions options,
+ @Nullable ServiceConnection connection);
+
+ /**
+ * Stop a foreground service delegate.
+ * @param options the foreground service delegate options.
+ * @hide
+ */
+ public abstract void stopForegroundServiceDelegate(
+ @NonNull ForegroundServiceDelegationOptions options);
+
+ /**
+ * Stop a foreground service delegate by service connection.
+ * @param connection service connection used to start delegate previously.
+ * @hide
+ */
+ public abstract void stopForegroundServiceDelegate(@NonNull ServiceConnection connection);
}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 86482c0..3761251 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -784,9 +784,10 @@
static final class ReceiverData extends BroadcastReceiver.PendingResult {
public ReceiverData(Intent intent, int resultCode, String resultData, Bundle resultExtras,
- boolean ordered, boolean sticky, IBinder token, int sendingUser) {
+ boolean ordered, boolean sticky, boolean assumeDelivered, IBinder token,
+ int sendingUser) {
super(resultCode, resultData, resultExtras, TYPE_COMPONENT, ordered, sticky,
- token, sendingUser, intent.getFlags());
+ assumeDelivered, token, sendingUser, intent.getFlags());
this.intent = intent;
}
@@ -1040,10 +1041,10 @@
public final void scheduleReceiver(Intent intent, ActivityInfo info,
CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,
- boolean sync, int sendingUser, int processState) {
+ boolean ordered, boolean assumeDelivered, int sendingUser, int processState) {
updateProcessState(processState, false);
ReceiverData r = new ReceiverData(intent, resultCode, data, extras,
- sync, false, mAppThread.asBinder(), sendingUser);
+ ordered, false, assumeDelivered, mAppThread.asBinder(), sendingUser);
r.info = info;
sendMessage(H.RECEIVER, r);
}
@@ -1054,11 +1055,11 @@
if (r.registered) {
scheduleRegisteredReceiver(r.receiver, r.intent,
r.resultCode, r.data, r.extras, r.ordered, r.sticky,
- r.sendingUser, r.processState);
+ r.assumeDelivered, r.sendingUser, r.processState);
} else {
scheduleReceiver(r.intent, r.activityInfo, r.compatInfo,
r.resultCode, r.data, r.extras, r.sync,
- r.sendingUser, r.processState);
+ r.assumeDelivered, r.sendingUser, r.processState);
}
}
}
@@ -1288,10 +1289,25 @@
// applies transaction ordering per object for such calls.
public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
int resultCode, String dataStr, Bundle extras, boolean ordered,
- boolean sticky, int sendingUser, int processState) throws RemoteException {
+ boolean sticky, boolean assumeDelivered, int sendingUser, int processState)
+ throws RemoteException {
updateProcessState(processState, false);
- receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
- sticky, sendingUser);
+
+ // We can't modify IIntentReceiver due to UnsupportedAppUsage, so
+ // try our best to shortcut to known subclasses, and alert if
+ // registered using a custom IIntentReceiver that isn't able to
+ // report an expected delivery event
+ if (receiver instanceof LoadedApk.ReceiverDispatcher.InnerReceiver) {
+ ((LoadedApk.ReceiverDispatcher.InnerReceiver) receiver).performReceive(intent,
+ resultCode, dataStr, extras, ordered, sticky, assumeDelivered, sendingUser);
+ } else {
+ if (!assumeDelivered) {
+ Log.wtf(TAG, "scheduleRegisteredReceiver() called for " + receiver
+ + " and " + intent + " without mechanism to finish delivery");
+ }
+ receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky,
+ sendingUser);
+ }
}
@Override
@@ -2640,7 +2656,7 @@
ClassLoader baseLoader, boolean securityViolation, boolean includeCode,
boolean registerPackage) {
return getPackageInfo(aInfo, compatInfo, baseLoader, securityViolation, includeCode,
- registerPackage, /*isSdkSandbox=*/false);
+ registerPackage, Process.isSdkSandbox());
}
private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
@@ -4558,7 +4574,11 @@
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
if (!service.isUiContext()) { // WindowProviderService is a UI Context.
- service.updateDeviceId(mLastReportedDeviceId);
+ VirtualDeviceManager vdm = context.getSystemService(VirtualDeviceManager.class);
+ if (mLastReportedDeviceId == VirtualDeviceManager.DEVICE_ID_DEFAULT
+ || vdm.isValidVirtualDeviceId(mLastReportedDeviceId)) {
+ service.updateDeviceId(mLastReportedDeviceId);
+ }
}
service.onCreate();
mServicesData.put(data.token, data);
@@ -6865,26 +6885,13 @@
final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
final StrictMode.ThreadPolicy writesAllowedPolicy = StrictMode.getThreadPolicy();
- // Wait for debugger after we have notified the system to finish attach application
if (data.debugMode != ApplicationThreadConstants.DEBUG_OFF) {
if (data.debugMode == ApplicationThreadConstants.DEBUG_WAIT) {
- Slog.w(TAG, "Application " + data.info.getPackageName()
- + " is waiting for the debugger ...");
-
- try {
- mgr.showWaitingForDebugger(mAppThread, true);
- } catch (RemoteException ex) {
- throw ex.rethrowFromSystemServer();
- }
-
- Debug.waitForDebugger();
-
- try {
- mgr.showWaitingForDebugger(mAppThread, false);
- } catch (RemoteException ex) {
- throw ex.rethrowFromSystemServer();
- }
+ waitForDebugger(data);
+ } else if (data.debugMode == ApplicationThreadConstants.DEBUG_SUSPEND) {
+ suspendAllAndSendVmStart(data);
}
+ // Nothing special to do in case of DEBUG_ON.
}
try {
@@ -6968,6 +6975,49 @@
}
}
+ @UnsupportedAppUsage
+ private void waitForDebugger(AppBindData data) {
+ final IActivityManager mgr = ActivityManager.getService();
+ Slog.w(TAG, "Application " + data.info.getPackageName()
+ + " is waiting for the debugger ...");
+
+ try {
+ mgr.showWaitingForDebugger(mAppThread, true);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+
+ Debug.waitForDebugger();
+
+ try {
+ mgr.showWaitingForDebugger(mAppThread, false);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ @UnsupportedAppUsage
+ private void suspendAllAndSendVmStart(AppBindData data) {
+ final IActivityManager mgr = ActivityManager.getService();
+ Slog.w(TAG, "Application " + data.info.getPackageName()
+ + " is suspending. Debugger needs to resume to continue.");
+
+ try {
+ mgr.showWaitingForDebugger(mAppThread, true);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+
+ Debug.suspendAllAndSendVmStart();
+
+ try {
+ mgr.showWaitingForDebugger(mAppThread, false);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+
private void handleSetContentCaptureOptionsCallback(String packageName) {
if (mContentCaptureOptionsCallback != null) {
return;
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 563f6d4..a14f3d3 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -2489,7 +2489,7 @@
"RECEIVE_EXPLICIT_USER_INTERACTION_AUDIO").setDefaultMode(
AppOpsManager.MODE_ALLOWED).build(),
new AppOpInfo.Builder(OP_RUN_LONG_JOBS, OPSTR_RUN_LONG_JOBS, "RUN_LONG_JOBS")
- .setPermission(Manifest.permission.RUN_LONG_JOBS).build(),
+ .setDefaultMode(AppOpsManager.MODE_ALLOWED).build(),
new AppOpInfo.Builder(OP_READ_MEDIA_VISUAL_USER_SELECTED,
OPSTR_READ_MEDIA_VISUAL_USER_SELECTED, "READ_MEDIA_VISUAL_USER_SELECTED")
.setPermission(Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED)
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index a7a4b35..c11961e 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -3890,4 +3890,14 @@
return Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.SHOW_NEW_APP_INSTALLED_NOTIFICATION_ENABLED, 0) == 1;
}
+
+ @Override
+ public void relinquishUpdateOwnership(String targetPackage) {
+ Objects.requireNonNull(targetPackage);
+ try {
+ mPM.relinquishUpdateOwnership(targetPackage);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/android/app/ApplicationThreadConstants.java b/core/java/android/app/ApplicationThreadConstants.java
index 1fa670f..c7620c3 100644
--- a/core/java/android/app/ApplicationThreadConstants.java
+++ b/core/java/android/app/ApplicationThreadConstants.java
@@ -28,6 +28,7 @@
public static final int DEBUG_OFF = 0;
public static final int DEBUG_ON = 1;
public static final int DEBUG_WAIT = 2;
+ public static final int DEBUG_SUSPEND = 3;
// the package has been removed, clean up internal references
public static final int PACKAGE_REMOVED = 0;
@@ -36,4 +37,4 @@
public static final int PACKAGE_REMOVED_DONT_KILL = 2;
// a previously removed package was replaced with a new version [eg. upgrade, split added, ...]
public static final int PACKAGE_REPLACED = 3;
-}
\ No newline at end of file
+}
diff --git a/core/java/android/app/BroadcastOptions.java b/core/java/android/app/BroadcastOptions.java
index e202760..5cf10d0 100644
--- a/core/java/android/app/BroadcastOptions.java
+++ b/core/java/android/app/BroadcastOptions.java
@@ -63,6 +63,7 @@
private long mRequireCompatChangeId = CHANGE_INVALID;
private boolean mRequireCompatChangeEnabled = true;
private boolean mIsAlarmBroadcast = false;
+ private boolean mIsDeferUntilActive = false;
private long mIdForResponseEvent;
private @Nullable IntentFilter mRemoveMatchingFilter;
private @DeliveryGroupPolicy int mDeliveryGroupPolicy;
@@ -201,6 +202,12 @@
"android:broadcast.removeMatchingFilter";
/**
+ * Corresponds to {@link #setDeferUntilActive(boolean)}.
+ */
+ private static final String KEY_DEFER_UNTIL_ACTIVE =
+ "android:broadcast.deferuntilactive";
+
+ /**
* Corresponds to {@link #setDeliveryGroupPolicy(int)}.
*/
private static final String KEY_DELIVERY_GROUP_POLICY =
@@ -320,6 +327,7 @@
BundleMerger.class);
mDeliveryGroupMatchingFilter = opts.getParcelable(KEY_DELIVERY_GROUP_MATCHING_FILTER,
IntentFilter.class);
+ mIsDeferUntilActive = opts.getBoolean(KEY_DEFER_UNTIL_ACTIVE, false);
}
/**
@@ -700,6 +708,41 @@
}
/**
+ * Sets whether the broadcast should not run until the process is in an active process state
+ * (ie, a process exists for the app and the app is not in a cached process state).
+ *
+ * Whether an app's process state is considered active is independent of its standby bucket.
+ *
+ * A broadcast that is deferred until the process is active will not execute until the process
+ * is brought to an active state by some other action, like a job, alarm, or service binding. As
+ * a result, the broadcast may be delayed indefinitely. This deferral only applies to runtime
+ * registered receivers of a broadcast. Any manifest receivers will run immediately, similar to
+ * how a manifest receiver would start a new process in order to run a broadcast receiver.
+ *
+ * Ordered broadcasts, alarm broadcasts, interactive broadcasts, and manifest broadcasts are
+ * never deferred.
+ *
+ * Unordered broadcasts and unordered broadcasts with completion callbacks may be
+ * deferred. Completion callbacks for broadcasts deferred until active are
+ * best-effort. Completion callbacks will run when all eligible processes have finished
+ * executing the broadcast. Processes in inactive process states that defer the broadcast are
+ * not considered eligible and may not execute the broadcast prior to the completion callback.
+ *
+ * @hide
+ */
+ @SystemApi
+ public @NonNull BroadcastOptions setDeferUntilActive(boolean shouldDefer) {
+ mIsDeferUntilActive = shouldDefer;
+ return this;
+ }
+
+ /** @hide */
+ @SystemApi
+ public boolean isDeferUntilActive() {
+ return mIsDeferUntilActive;
+ }
+
+ /**
* When enqueuing this broadcast, remove all pending broadcasts previously
* sent by this app which match the given filter.
* <p>
@@ -963,6 +1006,9 @@
if (mDeliveryGroupMatchingFilter != null) {
b.putParcelable(KEY_DELIVERY_GROUP_MATCHING_FILTER, mDeliveryGroupMatchingFilter);
}
+ if (mIsDeferUntilActive) {
+ b.putBoolean(KEY_DEFER_UNTIL_ACTIVE, mIsDeferUntilActive);
+ }
return b.isEmpty() ? null : b;
}
}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index befe833a..b91fa35 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -2582,6 +2582,22 @@
}
@Override
+ public Context createContextForSdkInSandbox(ApplicationInfo sdkInfo, int flags)
+ throws NameNotFoundException {
+ if (!Process.isSdkSandbox()) {
+ throw new SecurityException("API can only be called from SdkSandbox process");
+ }
+
+ ContextImpl ctx = (ContextImpl) createApplicationContext(sdkInfo, flags);
+
+ // Set sandbox app's context as the application context for sdk context
+ ctx.mPackageInfo.makeApplicationInner(/*forceDefaultAppClass=*/false,
+ /*instrumentation=*/null);
+
+ return ctx;
+ }
+
+ @Override
public Context createPackageContext(String packageName, int flags)
throws NameNotFoundException {
return createPackageContextAsUser(packageName, flags, mUser);
@@ -3032,8 +3048,11 @@
throw new UnsupportedOperationException(
"Cannot update device ID on a Context created with createDeviceContext()");
}
- mDeviceId = updatedDeviceId;
- notifyOnDeviceChangedListeners(updatedDeviceId);
+
+ if (mDeviceId != updatedDeviceId) {
+ mDeviceId = updatedDeviceId;
+ notifyOnDeviceChangedListeners(updatedDeviceId);
+ }
}
@Override
diff --git a/services/core/java/com/android/server/am/ForegroundServiceDelegationOptions.java b/core/java/android/app/ForegroundServiceDelegationOptions.java
similarity index 91%
rename from services/core/java/com/android/server/am/ForegroundServiceDelegationOptions.java
rename to core/java/android/app/ForegroundServiceDelegationOptions.java
index 5eb5a55..875e01f 100644
--- a/services/core/java/com/android/server/am/ForegroundServiceDelegationOptions.java
+++ b/core/java/android/app/ForegroundServiceDelegationOptions.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,12 +14,11 @@
* limitations under the License.
*/
-package com.android.server.am;
+package android.app;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.app.IApplicationThread;
import android.content.ComponentName;
import java.lang.annotation.Retention;
@@ -32,6 +31,8 @@
* is higher than the app's actual process state if the app is in the background. This can help to
* keep the app in the memory and extra run-time.
* The app does not need to define an actual service component nor add it into manifest file.
+ *
+ * @hide
*/
public class ForegroundServiceDelegationOptions {
@@ -191,6 +192,11 @@
}
}
+ /**
+ * The helper class to build the instance of {@link ForegroundServiceDelegate}.
+ *
+ * @hide
+ */
public static class Builder {
int mClientPid; // The actual app PID
int mClientUid; // The actual app UID
@@ -202,51 +208,81 @@
int mForegroundServiceTypes; // The foreground service types it consists of
@DelegationService int mDelegationService; // The internal service's name, i.e. VOIP
+ /**
+ * Set the client app's PID.
+ */
public Builder setClientPid(int clientPid) {
mClientPid = clientPid;
return this;
}
+ /**
+ * Set the client app's UID.
+ */
public Builder setClientUid(int clientUid) {
mClientUid = clientUid;
return this;
}
+ /**
+ * Set the client app's package name.
+ */
public Builder setClientPackageName(@NonNull String clientPackageName) {
mClientPackageName = clientPackageName;
return this;
}
+ /**
+ * Set the notification ID from the client app.
+ */
public Builder setClientNotificationId(int clientNotificationId) {
mClientNotificationId = clientNotificationId;
return this;
}
+ /**
+ * Set the client app's application thread.
+ */
public Builder setClientAppThread(@NonNull IApplicationThread clientAppThread) {
mClientAppThread = clientAppThread;
return this;
}
+ /**
+ * Set the client instance of this service.
+ */
public Builder setClientInstanceName(@NonNull String clientInstanceName) {
mClientInstanceName = clientInstanceName;
return this;
}
+ /**
+ * Set stickiness of this service.
+ */
public Builder setSticky(boolean isSticky) {
mSticky = isSticky;
return this;
}
+ /**
+ * Set the foreground service type.
+ */
public Builder setForegroundServiceTypes(int foregroundServiceTypes) {
mForegroundServiceTypes = foregroundServiceTypes;
return this;
}
+ /**
+ * Set the delegation service type.
+ */
public Builder setDelegationService(@DelegationService int delegationService) {
mDelegationService = delegationService;
return this;
}
+ /**
+ * @return An instance of {@link ForegroundServiceDelegationOptions}.
+ */
public ForegroundServiceDelegationOptions build() {
return new ForegroundServiceDelegationOptions(mClientPid,
mClientUid,
diff --git a/core/java/android/app/ForegroundServiceTypePolicy.java b/core/java/android/app/ForegroundServiceTypePolicy.java
index 877177c..c19a865 100644
--- a/core/java/android/app/ForegroundServiceTypePolicy.java
+++ b/core/java/android/app/ForegroundServiceTypePolicy.java
@@ -117,14 +117,10 @@
* The FGS type enforcement:
* deprecating the {@link android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_DATA_SYNC}.
*
- * <p>Starting a FGS with this type from apps with targetSdkVersion
- * {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} or later will
- * result in a warning in the log.</p>
- *
* @hide
*/
@ChangeId
- @EnabledAfter(targetSdkVersion = android.os.Build.VERSION_CODES.TIRAMISU)
+ @Disabled
@Overridable
public static final long FGS_TYPE_DATA_SYNC_DEPRECATION_CHANGE_ID = 255039210L;
@@ -132,13 +128,8 @@
* The FGS type enforcement:
* disabling the {@link android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_DATA_SYNC}.
*
- * <p>Starting a FGS with this type from apps with targetSdkVersion
- * {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} or later will
- * result in an exception.</p>
- *
* @hide
*/
- // TODO (b/254661666): Change to @EnabledSince(U) in next OS release
@ChangeId
@Disabled
@Overridable
@@ -268,12 +259,15 @@
new RegularPermission(Manifest.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE)
}, true),
new ForegroundServiceTypePermissions(new ForegroundServiceTypePermission[] {
+ new RegularPermission(Manifest.permission.BLUETOOTH_ADVERTISE),
new RegularPermission(Manifest.permission.BLUETOOTH_CONNECT),
+ new RegularPermission(Manifest.permission.BLUETOOTH_SCAN),
new RegularPermission(Manifest.permission.CHANGE_NETWORK_STATE),
new RegularPermission(Manifest.permission.CHANGE_WIFI_STATE),
new RegularPermission(Manifest.permission.CHANGE_WIFI_MULTICAST_STATE),
new RegularPermission(Manifest.permission.NFC),
new RegularPermission(Manifest.permission.TRANSMIT_IR),
+ new RegularPermission(Manifest.permission.UWB_RANGING),
new UsbDevicePermission(),
new UsbAccessoryPermission(),
}, false)
diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl
index 3984fee..4f69d85 100644
--- a/core/java/android/app/IApplicationThread.aidl
+++ b/core/java/android/app/IApplicationThread.aidl
@@ -65,8 +65,8 @@
oneway interface IApplicationThread {
void scheduleReceiver(in Intent intent, in ActivityInfo info,
in CompatibilityInfo compatInfo,
- int resultCode, in String data, in Bundle extras, boolean sync,
- int sendingUser, int processState);
+ int resultCode, in String data, in Bundle extras, boolean ordered,
+ boolean assumeDelivered, int sendingUser, int processState);
void scheduleReceiverList(in List<ReceiverInfo> info);
@@ -102,7 +102,7 @@
in String[] args);
void scheduleRegisteredReceiver(IIntentReceiver receiver, in Intent intent,
int resultCode, in String data, in Bundle extras, boolean ordered,
- boolean sticky, int sendingUser, int processState);
+ boolean sticky, boolean assumeDelivered, int sendingUser, int processState);
void scheduleLowMemory();
void profilerControl(boolean start, in ProfilerInfo profilerInfo, int profileType);
void setSchedulingGroup(int group);
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 3620a60..7c22902 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -1679,6 +1679,16 @@
@Override
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
+ Log.wtf(TAG, "performReceive() called targeting raw IIntentReceiver for " + intent);
+ performReceive(intent, resultCode, data, extras, ordered, sticky,
+ BroadcastReceiver.PendingResult.guessAssumeDelivered(
+ BroadcastReceiver.PendingResult.TYPE_REGISTERED, ordered),
+ sendingUser);
+ }
+
+ public void performReceive(Intent intent, int resultCode, String data,
+ Bundle extras, boolean ordered, boolean sticky, boolean assumeDelivered,
+ int sendingUser) {
final LoadedApk.ReceiverDispatcher rd;
if (intent == null) {
Log.wtf(TAG, "Null intent received");
@@ -1693,8 +1703,8 @@
}
if (rd != null) {
rd.performReceive(intent, resultCode, data, extras,
- ordered, sticky, sendingUser);
- } else {
+ ordered, sticky, assumeDelivered, sendingUser);
+ } else if (!assumeDelivered) {
// The activity manager dispatched a broadcast to a registered
// receiver in this process, but before it could be delivered the
// receiver was unregistered. Acknowledge the broadcast on its
@@ -1729,30 +1739,26 @@
final class Args extends BroadcastReceiver.PendingResult {
private Intent mCurIntent;
- private final boolean mOrdered;
private boolean mDispatched;
private boolean mRunCalled;
public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras,
- boolean ordered, boolean sticky, int sendingUser) {
+ boolean ordered, boolean sticky, boolean assumeDelivered, int sendingUser) {
super(resultCode, resultData, resultExtras,
mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED, ordered,
- sticky, mAppThread.asBinder(), sendingUser, intent.getFlags());
+ sticky, assumeDelivered, mAppThread.asBinder(), sendingUser,
+ intent.getFlags());
mCurIntent = intent;
- mOrdered = ordered;
}
public final Runnable getRunnable() {
return () -> {
final BroadcastReceiver receiver = mReceiver;
- final boolean ordered = mOrdered;
if (ActivityThread.DEBUG_BROADCAST) {
int seq = mCurIntent.getIntExtra("seq", -1);
Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction()
+ " seq=" + seq + " to " + mReceiver);
- Slog.i(ActivityThread.TAG, " mRegistered=" + mRegistered
- + " mOrderedHint=" + ordered);
}
final IActivityManager mgr = ActivityManager.getService();
@@ -1766,11 +1772,9 @@
mDispatched = true;
mRunCalled = true;
if (receiver == null || intent == null || mForgotten) {
- if (mRegistered && ordered) {
- if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
- "Finishing null broadcast to " + mReceiver);
- sendFinished(mgr);
- }
+ if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
+ "Finishing null broadcast to " + mReceiver);
+ sendFinished(mgr);
return;
}
@@ -1790,11 +1794,9 @@
receiver.setPendingResult(this);
receiver.onReceive(mContext, intent);
} catch (Exception e) {
- if (mRegistered && ordered) {
- if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
- "Finishing failed broadcast to " + mReceiver);
- sendFinished(mgr);
- }
+ if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
+ "Finishing failed broadcast to " + mReceiver);
+ sendFinished(mgr);
if (mInstrumentation == null ||
!mInstrumentation.onException(mReceiver, e)) {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
@@ -1868,9 +1870,10 @@
}
public void performReceive(Intent intent, int resultCode, String data,
- Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
+ Bundle extras, boolean ordered, boolean sticky, boolean assumeDelivered,
+ int sendingUser) {
final Args args = new Args(intent, resultCode, data, extras, ordered,
- sticky, sendingUser);
+ sticky, assumeDelivered, sendingUser);
if (intent == null) {
Log.wtf(TAG, "Null intent received");
} else {
@@ -1881,12 +1884,10 @@
}
}
if (intent == null || !mActivityThread.post(args.getRunnable())) {
- if (mRegistered && ordered) {
- IActivityManager mgr = ActivityManager.getService();
- if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
- "Finishing sync broadcast to " + mReceiver);
- args.sendFinished(mgr);
- }
+ IActivityManager mgr = ActivityManager.getService();
+ if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
+ "Finishing sync broadcast to " + mReceiver);
+ args.sendFinished(mgr);
}
}
diff --git a/core/java/android/app/LocaleConfig.java b/core/java/android/app/LocaleConfig.java
index 50ba7db..69693fc 100644
--- a/core/java/android/app/LocaleConfig.java
+++ b/core/java/android/app/LocaleConfig.java
@@ -110,7 +110,7 @@
* @see Context#createPackageContext(String, int).
*/
@NonNull
- public static LocaleConfig fromResources(@NonNull Context context) {
+ public static LocaleConfig fromContextIgnoringOverride(@NonNull Context context) {
return new LocaleConfig(context, false);
}
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index f9ef3cc..c081d82 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1782,7 +1782,7 @@
* @deprecated Use {@link android.app.Notification.Action.Builder}.
*/
@Deprecated
- public Action(int icon, CharSequence title, PendingIntent intent) {
+ public Action(int icon, CharSequence title, @Nullable PendingIntent intent) {
this(Icon.createWithResource("", icon), title, intent, new Bundle(), null, true,
SEMANTIC_ACTION_NONE, false /* isContextual */, false /* requireAuth */);
}
@@ -1907,10 +1907,12 @@
* which may display them in other contexts, for example on a wearable device.
* @param icon icon to show for this action
* @param title the title of the action
- * @param intent the {@link PendingIntent} to fire when users trigger this action
+ * @param intent the {@link PendingIntent} to fire when users trigger this action. May
+ * be null, in which case the action may be rendered in a disabled presentation by the
+ * system UI.
*/
@Deprecated
- public Builder(int icon, CharSequence title, PendingIntent intent) {
+ public Builder(int icon, CharSequence title, @Nullable PendingIntent intent) {
this(Icon.createWithResource("", icon), title, intent);
}
@@ -1939,9 +1941,11 @@
*
* @param icon icon to show for this action
* @param title the title of the action
- * @param intent the {@link PendingIntent} to fire when users trigger this action
+ * @param intent the {@link PendingIntent} to fire when users trigger this action. May
+ * be null, in which case the action may be rendered in a disabled presentation by the
+ * system UI.
*/
- public Builder(Icon icon, CharSequence title, PendingIntent intent) {
+ public Builder(Icon icon, CharSequence title, @Nullable PendingIntent intent) {
this(icon, title, intent, new Bundle(), null, true, SEMANTIC_ACTION_NONE, false);
}
diff --git a/core/java/android/app/OWNERS b/core/java/android/app/OWNERS
index f2eced3..20869e0 100644
--- a/core/java/android/app/OWNERS
+++ b/core/java/android/app/OWNERS
@@ -47,6 +47,9 @@
# AppOps
per-file *AppOp* = file:/core/java/android/permission/OWNERS
+# Backup and Restore
+per-file IBackupAgent.aidl = file:/services/backup/OWNERS
+
# LocaleManager
per-file *Locale* = file:/services/core/java/com/android/server/locales/OWNERS
diff --git a/core/java/android/app/ReceiverInfo.aidl b/core/java/android/app/ReceiverInfo.aidl
index d90eee7..8d7e3c4 100644
--- a/core/java/android/app/ReceiverInfo.aidl
+++ b/core/java/android/app/ReceiverInfo.aidl
@@ -34,6 +34,7 @@
Intent intent;
String data;
Bundle extras;
+ boolean assumeDelivered;
int sendingUser;
int processState;
int resultCode;
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index ad27b33..e485397 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -1080,7 +1080,6 @@
if (mForegroundServiceTraceTitle != null) {
Trace.asyncTraceForTrackEnd(TRACE_TAG_ACTIVITY_MANAGER,
TRACE_TRACK_NAME_FOREGROUND_SERVICE,
- mForegroundServiceTraceTitle,
System.identityHashCode(this));
mForegroundServiceTraceTitle = null;
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index ad17e0d..33721a0 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -19,6 +19,7 @@
import static android.Manifest.permission.QUERY_ADMIN_POLICY;
import static android.Manifest.permission.SET_TIME;
import static android.Manifest.permission.SET_TIME_ZONE;
+import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.content.Intent.LOCAL_FLAG_FROM_SYSTEM;
import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_1;
@@ -2417,6 +2418,7 @@
* applied (cross profile intent filters updated). Only usesd for CTS tests.
* @hide
*/
+ @SuppressLint("ActionValue")
@TestApi
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_DATA_SHARING_RESTRICTION_APPLIED =
@@ -2427,6 +2429,7 @@
* has been changed.
* @hide
*/
+ @SuppressLint("ActionValue")
@TestApi
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_DEVICE_POLICY_CONSTANTS_CHANGED =
@@ -4184,7 +4187,7 @@
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
+ @RequiresPermission(INTERACT_ACROSS_USERS_FULL)
public boolean packageHasActiveAdmins(String packageName) {
return packageHasActiveAdmins(packageName, myUserId());
}
@@ -6979,6 +6982,8 @@
* {@link #ENCRYPTION_STATUS_UNSUPPORTED}, {@link #ENCRYPTION_STATUS_INACTIVE},
* {@link #ENCRYPTION_STATUS_ACTIVATING}, {@link #ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY},
* {@link #ENCRYPTION_STATUS_ACTIVE}, or {@link #ENCRYPTION_STATUS_ACTIVE_PER_USER}.
+ *
+ * @throws SecurityException if called on a parent instance.
*/
public int getStorageEncryptionStatus() {
throwIfParentInstance("getStorageEncryptionStatus");
@@ -8739,7 +8744,7 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@RequiresPermission(allOf = {
android.Manifest.permission.MANAGE_DEVICE_ADMINS,
- android.Manifest.permission.INTERACT_ACROSS_USERS_FULL
+ INTERACT_ACROSS_USERS_FULL
})
public void setActiveAdmin(@NonNull ComponentName policyReceiver, boolean refreshing,
int userHandle) {
@@ -10650,7 +10655,7 @@
*/
@UserHandleAware
@RequiresPermission(allOf = {
- android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+ INTERACT_ACROSS_USERS_FULL,
android.Manifest.permission.MANAGE_USERS
}, conditional = true)
public @Nullable List<String> getPermittedInputMethods() {
@@ -14841,7 +14846,7 @@
* @hide
*/
@RequiresPermission(anyOf = {
- permission.INTERACT_ACROSS_USERS_FULL,
+ INTERACT_ACROSS_USERS_FULL,
permission.INTERACT_ACROSS_USERS
}, conditional = true)
public boolean isPackageAllowedToAccessCalendar(@NonNull String packageName) {
@@ -14873,7 +14878,7 @@
* @hide
*/
@RequiresPermission(anyOf = {
- permission.INTERACT_ACROSS_USERS_FULL,
+ INTERACT_ACROSS_USERS_FULL,
permission.INTERACT_ACROSS_USERS
})
public @Nullable Set<String> getCrossProfileCalendarPackages() {
@@ -14966,7 +14971,7 @@
* @hide
*/
@RequiresPermission(anyOf = {
- permission.INTERACT_ACROSS_USERS_FULL,
+ INTERACT_ACROSS_USERS_FULL,
permission.INTERACT_ACROSS_USERS,
permission.INTERACT_ACROSS_PROFILES
})
@@ -16150,6 +16155,23 @@
}
/**
+ * Reset cache for {@link #shouldAllowBypassingDevicePolicyManagementRoleQualification}.
+ *
+ * @hide
+ */
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS)
+ public void resetShouldAllowBypassingDevicePolicyManagementRoleQualificationState() {
+ if (mService != null) {
+ try {
+ mService.resetShouldAllowBypassingDevicePolicyManagementRoleQualificationState();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+ /**
* @return {@code true} if bypassing the device policy management role qualification is allowed
* with the current state of the device.
*
diff --git a/core/java/android/app/admin/EnterprisePlatformSecurity_OWNERS b/core/java/android/app/admin/EnterprisePlatformSecurity_OWNERS
index 0ec8253..270cb18 100644
--- a/core/java/android/app/admin/EnterprisePlatformSecurity_OWNERS
+++ b/core/java/android/app/admin/EnterprisePlatformSecurity_OWNERS
@@ -1,5 +1,4 @@
rubinxu@google.com
-acjohnston@google.com
pgrafov@google.com
ayushsha@google.com
alexkershaw@google.com #{LAST_RESORT_SUGGESTION}
\ No newline at end of file
diff --git a/core/java/android/app/admin/EnterprisePlatform_OWNERS b/core/java/android/app/admin/EnterprisePlatform_OWNERS
index fb00fe5..6ce25cc 100644
--- a/core/java/android/app/admin/EnterprisePlatform_OWNERS
+++ b/core/java/android/app/admin/EnterprisePlatform_OWNERS
@@ -1,2 +1,5 @@
+# Assign bugs to android-enterprise-triage@google.com
file:WorkDeviceExperience_OWNERS
+file:Provisioning_OWNERS
+file:WorkProfile_OWNERS
file:EnterprisePlatformSecurity_OWNERS
\ No newline at end of file
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 20695ca..aebeaf0 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -575,6 +575,7 @@
void resetStrings(in List<String> stringIds);
ParcelableResource getString(String stringId);
+ void resetShouldAllowBypassingDevicePolicyManagementRoleQualificationState();
boolean shouldAllowBypassingDevicePolicyManagementRoleQualification();
List<UserHandle> getPolicyManagedProfiles(in UserHandle userHandle);
diff --git a/core/java/android/app/admin/PolicyUpdatesReceiver.java b/core/java/android/app/admin/PolicyUpdatesReceiver.java
index 3ad3157..f7216e7 100644
--- a/core/java/android/app/admin/PolicyUpdatesReceiver.java
+++ b/core/java/android/app/admin/PolicyUpdatesReceiver.java
@@ -21,7 +21,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
-import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -109,8 +108,6 @@
public static final String ACTION_DEVICE_POLICY_CHANGED =
"android.app.admin.action.DEVICE_POLICY_CHANGED";
- // TODO(b/264510719): Remove once API linter is fixed
- @SuppressLint("ActionValue")
/**
* A string extra holding the package name the policy applies to, (see
* {@link PolicyUpdatesReceiver#onPolicyChanged} and
@@ -119,8 +116,6 @@
public static final String EXTRA_PACKAGE_NAME =
"android.app.admin.extra.PACKAGE_NAME";
- // TODO(b/264510719): Remove once API linter is fixed
- @SuppressLint("ActionValue")
/**
* A string extra holding the permission name the policy applies to, (see
* {@link PolicyUpdatesReceiver#onPolicyChanged} and
diff --git a/core/java/android/app/admin/PreferentialNetworkServiceConfig.java b/core/java/android/app/admin/PreferentialNetworkServiceConfig.java
index b0ea499..0513099 100644
--- a/core/java/android/app/admin/PreferentialNetworkServiceConfig.java
+++ b/core/java/android/app/admin/PreferentialNetworkServiceConfig.java
@@ -51,6 +51,7 @@
final boolean mIsEnabled;
final int mNetworkId;
final boolean mAllowFallbackToDefaultConnection;
+ final boolean mShouldBlockNonMatchingNetworks;
final int[] mIncludedUids;
final int[] mExcludedUids;
@@ -64,6 +65,8 @@
"preferential_network_service_network_id";
private static final String TAG_ALLOW_FALLBACK_TO_DEFAULT_CONNECTION =
"allow_fallback_to_default_connection";
+ private static final String TAG_BLOCK_NON_MATCHING_NETWORKS =
+ "block_non_matching_networks";
private static final String TAG_INCLUDED_UIDS = "included_uids";
private static final String TAG_EXCLUDED_UIDS = "excluded_uids";
private static final String ATTR_VALUE = "value";
@@ -111,10 +114,12 @@
}
private PreferentialNetworkServiceConfig(boolean isEnabled,
- boolean allowFallbackToDefaultConnection, int[] includedUids,
+ boolean allowFallbackToDefaultConnection, boolean shouldBlockNonMatchingNetworks,
+ int[] includedUids,
int[] excludedUids, @PreferentialNetworkPreferenceId int networkId) {
mIsEnabled = isEnabled;
mAllowFallbackToDefaultConnection = allowFallbackToDefaultConnection;
+ mShouldBlockNonMatchingNetworks = shouldBlockNonMatchingNetworks;
mIncludedUids = includedUids;
mExcludedUids = excludedUids;
mNetworkId = networkId;
@@ -123,6 +128,7 @@
private PreferentialNetworkServiceConfig(Parcel in) {
mIsEnabled = in.readBoolean();
mAllowFallbackToDefaultConnection = in.readBoolean();
+ mShouldBlockNonMatchingNetworks = in.readBoolean();
mNetworkId = in.readInt();
mIncludedUids = in.createIntArray();
mExcludedUids = in.createIntArray();
@@ -137,9 +143,18 @@
}
/**
- * is fallback to default network allowed. This boolean configures whether default connection
- * (default internet or wifi) should be used or not if a preferential network service
- * connection is not available.
+ * Whether fallback to the device-wide default network is allowed.
+ *
+ * This boolean configures whether the default connection (e.g. general cell network or wifi)
+ * should be used if no preferential network service connection is available. If true, the
+ * default connection will be used when no preferential service is available. If false, the
+ * UIDs subject to this configuration will have no default network.
+ * Note that while this boolean determines whether the UIDs subject to this configuration have
+ * a default network in the absence of a preferential service, apps can still explicitly decide
+ * to use another network than their default network by requesting them from the system. This
+ * boolean does not determine whether the UIDs are blocked from using such other networks.
+ * See {@link #shouldBlockNonMatchingNetworks()} for that configuration.
+ *
* @return true if fallback is allowed, else false.
*/
public boolean isFallbackToDefaultConnectionAllowed() {
@@ -147,6 +162,21 @@
}
/**
+ * Whether to block UIDs from using other networks than the preferential service.
+ *
+ * Apps can inspect the list of available networks on the device and choose to use multiple
+ * of them concurrently for performance, privacy or other reasons.
+ * This boolean configures whether the concerned UIDs should be blocked from using
+ * networks that do not match the configured preferential network service even if these
+ * networks are otherwise open to all apps.
+ *
+ * @return true if UIDs should be blocked from using the other networks, else false.
+ */
+ public boolean shouldBlockNonMatchingNetworks() {
+ return mShouldBlockNonMatchingNetworks;
+ }
+
+ /**
* Get the array of uids that are applicable for the profile preference.
*
* {@see #getExcludedUids()}
@@ -190,6 +220,7 @@
return "PreferentialNetworkServiceConfig{"
+ "mIsEnabled=" + isEnabled()
+ "mAllowFallbackToDefaultConnection=" + isFallbackToDefaultConnectionAllowed()
+ + "mBlockNonMatchingNetworks=" + shouldBlockNonMatchingNetworks()
+ "mIncludedUids=" + Arrays.toString(mIncludedUids)
+ "mExcludedUids=" + Arrays.toString(mExcludedUids)
+ "mNetworkId=" + mNetworkId
@@ -203,6 +234,7 @@
final PreferentialNetworkServiceConfig that = (PreferentialNetworkServiceConfig) o;
return mIsEnabled == that.mIsEnabled
&& mAllowFallbackToDefaultConnection == that.mAllowFallbackToDefaultConnection
+ && mShouldBlockNonMatchingNetworks == that.mShouldBlockNonMatchingNetworks
&& mNetworkId == that.mNetworkId
&& Arrays.equals(mIncludedUids, that.mIncludedUids)
&& Arrays.equals(mExcludedUids, that.mExcludedUids);
@@ -211,7 +243,8 @@
@Override
public int hashCode() {
return Objects.hash(mIsEnabled, mAllowFallbackToDefaultConnection,
- Arrays.hashCode(mIncludedUids), Arrays.hashCode(mExcludedUids), mNetworkId);
+ mShouldBlockNonMatchingNetworks, Arrays.hashCode(mIncludedUids),
+ Arrays.hashCode(mExcludedUids), mNetworkId);
}
/**
@@ -222,6 +255,7 @@
boolean mIsEnabled = false;
int mNetworkId = 0;
boolean mAllowFallbackToDefaultConnection = true;
+ boolean mShouldBlockNonMatchingNetworks = false;
int[] mIncludedUids = new int[0];
int[] mExcludedUids = new int[0];
@@ -243,10 +277,21 @@
}
/**
- * Set whether the default connection should be used as fallback.
- * This boolean configures whether the default connection (default internet or wifi)
- * should be used if a preferential network service connection is not available.
- * Default value is true
+ * Set whether fallback to the device-wide default network is allowed.
+ *
+ * This boolean configures whether the default connection (e.g. general cell network or
+ * wifi) should be used if no preferential network service connection is available. If true,
+ * the default connection will be used when no preferential service is available. If false,
+ * the UIDs subject to this configuration will have no default network.
+ * Note that while this boolean determines whether the UIDs subject to this configuration
+ * have a default network in the absence of a preferential service, apps can still
+ * explicitly decide to use another network than their default network by requesting them
+ * from the system. This boolean does not determine whether the UIDs are blocked from using
+ * such other networks.
+ * Use {@link #setShouldBlockNonMatchingNetworks(boolean)} to specify this.
+ *
+ * The default value is true.
+ *
* @param allowFallbackToDefaultConnection true if fallback is allowed else false
* @return The builder to facilitate chaining.
*/
@@ -259,6 +304,31 @@
}
/**
+ * Set whether to block UIDs from using other networks than the preferential service.
+ *
+ * Apps can inspect the list of available networks on the device and choose to use multiple
+ * of them concurrently for performance, privacy or other reasons.
+ * This boolean configures whether the concerned UIDs should be blocked from using
+ * networks that do not match the configured preferential network service even if these
+ * networks are otherwise open to all apps.
+ *
+ * The default value is false. This value can only be set to {@code true} if
+ * {@link #setFallbackToDefaultConnectionAllowed(boolean)} is set to {@code false}, because
+ * allowing fallback but blocking it does not make sense. Failure to comply with this
+ * constraint will throw when building the object.
+ *
+ * @param blockNonMatchingNetworks true if UIDs should be blocked from using non-matching
+ * networks.
+ * @return The builder to facilitate chaining.
+ */
+ @NonNull
+ public PreferentialNetworkServiceConfig.Builder setShouldBlockNonMatchingNetworks(
+ boolean blockNonMatchingNetworks) {
+ mShouldBlockNonMatchingNetworks = blockNonMatchingNetworks;
+ return this;
+ }
+
+ /**
* Set the array of uids whose network access will go through this preferential
* network service.
* {@see #setExcludedUids(int[])}
@@ -306,8 +376,13 @@
throw new IllegalStateException("Both includedUids and excludedUids "
+ "cannot be nonempty");
}
+ if (mShouldBlockNonMatchingNetworks && mAllowFallbackToDefaultConnection) {
+ throw new IllegalStateException("A config cannot both allow fallback and "
+ + "block non-matching networks");
+ }
return new PreferentialNetworkServiceConfig(mIsEnabled,
- mAllowFallbackToDefaultConnection, mIncludedUids, mExcludedUids, mNetworkId);
+ mAllowFallbackToDefaultConnection, mShouldBlockNonMatchingNetworks,
+ mIncludedUids, mExcludedUids, mNetworkId);
}
/**
@@ -332,6 +407,7 @@
public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
dest.writeBoolean(mIsEnabled);
dest.writeBoolean(mAllowFallbackToDefaultConnection);
+ dest.writeBoolean(mShouldBlockNonMatchingNetworks);
dest.writeInt(mNetworkId);
dest.writeIntArray(mIncludedUids);
dest.writeIntArray(mExcludedUids);
@@ -423,6 +499,9 @@
} else if (TAG_ALLOW_FALLBACK_TO_DEFAULT_CONNECTION.equals(tagDAM)) {
resultBuilder.setFallbackToDefaultConnectionAllowed(parser.getAttributeBoolean(
null, ATTR_VALUE, true));
+ } else if (TAG_BLOCK_NON_MATCHING_NETWORKS.equals(tagDAM)) {
+ resultBuilder.setShouldBlockNonMatchingNetworks(parser.getAttributeBoolean(
+ null, ATTR_VALUE, false));
} else if (TAG_INCLUDED_UIDS.equals(tagDAM)) {
resultBuilder.setIncludedUids(readStringListToIntArray(parser, TAG_UID));
} else if (TAG_EXCLUDED_UIDS.equals(tagDAM)) {
@@ -443,6 +522,8 @@
writeAttributeValueToXml(out, TAG_NETWORK_ID, getNetworkId());
writeAttributeValueToXml(out, TAG_ALLOW_FALLBACK_TO_DEFAULT_CONNECTION,
isFallbackToDefaultConnectionAllowed());
+ writeAttributeValueToXml(out, TAG_BLOCK_NON_MATCHING_NETWORKS,
+ shouldBlockNonMatchingNetworks());
writeAttributeValuesToXml(out, TAG_INCLUDED_UIDS, TAG_UID,
intArrayToStringList(getIncludedUids()));
writeAttributeValuesToXml(out, TAG_EXCLUDED_UIDS, TAG_UID,
@@ -460,6 +541,8 @@
pw.println(mIsEnabled);
pw.print("allowFallbackToDefaultConnection=");
pw.println(mAllowFallbackToDefaultConnection);
+ pw.print("blockNonMatchingNetworks=");
+ pw.println(mShouldBlockNonMatchingNetworks);
pw.print("includedUids=");
pw.println(mIncludedUids);
pw.print("excludedUids=");
diff --git a/core/java/android/app/admin/Provisioning_OWNERS b/core/java/android/app/admin/Provisioning_OWNERS
new file mode 100644
index 0000000..2e5c2df
--- /dev/null
+++ b/core/java/android/app/admin/Provisioning_OWNERS
@@ -0,0 +1,5 @@
+# Assign bugs to android-enterprise-triage@google.com
+mdb.ae-provisioning-reviews@google.com
+petuska@google.com #{LAST_RESORT_SUGGESTION}
+nupursn@google.com #{LAST_RESORT_SUGGESTION}
+shreyacsingh@google.com #{LAST_RESORT_SUGGESTION}
diff --git a/core/java/android/app/admin/WorkDeviceExperience_OWNERS b/core/java/android/app/admin/WorkDeviceExperience_OWNERS
index 82afddd..2033343 100644
--- a/core/java/android/app/admin/WorkDeviceExperience_OWNERS
+++ b/core/java/android/app/admin/WorkDeviceExperience_OWNERS
@@ -1,5 +1,7 @@
+# Assign bugs to android-enterprise-triage@google.com
work-device-experience+reviews@google.com
-scottjonathan@google.com
-kholoudm@google.com
-eliselliott@google.com
+scottjonathan@google.com #{LAST_RESORT_SUGGESTION}
+eliselliott@google.com #{LAST_RESORT_SUGGESTION}
+kholoudm@google.com #{LAST_RESORT_SUGGESTION}
+acjohnston@google.com #{LAST_RESORT_SUGGESTION}
alexkershaw@google.com #{LAST_RESORT_SUGGESTION}
diff --git a/core/java/android/app/admin/WorkProfile_OWNERS b/core/java/android/app/admin/WorkProfile_OWNERS
new file mode 100644
index 0000000..260b672
--- /dev/null
+++ b/core/java/android/app/admin/WorkProfile_OWNERS
@@ -0,0 +1,5 @@
+# Assign bugs to android-enterprise-triage@google.com
+liahav@google.com
+olit@google.com
+scottjonathan@google.com #{LAST_RESORT_SUGGESTION}
+alexkershaw@google.com #{LAST_RESORT_SUGGESTION}
\ No newline at end of file
diff --git a/core/java/android/app/time/UnixEpochTime.java b/core/java/android/app/time/UnixEpochTime.java
index 61cbc5e..0b8f7ee 100644
--- a/core/java/android/app/time/UnixEpochTime.java
+++ b/core/java/android/app/time/UnixEpochTime.java
@@ -124,7 +124,7 @@
@Override
public String toString() {
return "UnixEpochTime{"
- + "mElapsedRealtimeTimeMillis=" + mElapsedRealtimeMillis
+ + "mElapsedRealtimeMillis=" + mElapsedRealtimeMillis
+ ", mUnixEpochTimeMillis=" + mUnixEpochTimeMillis
+ '}';
}
diff --git a/core/java/android/app/timedetector/TimeDetector.java b/core/java/android/app/timedetector/TimeDetector.java
index f95d6d3..50a7da1 100644
--- a/core/java/android/app/timedetector/TimeDetector.java
+++ b/core/java/android/app/timedetector/TimeDetector.java
@@ -73,6 +73,18 @@
String SHELL_COMMAND_SUGGEST_NETWORK_TIME = "suggest_network_time";
/**
+ * A shell command that prints the current network time information.
+ * @hide
+ */
+ String SHELL_COMMAND_GET_NETWORK_TIME = "get_network_time";
+
+ /**
+ * A shell command that clears the detector's network time information.
+ * @hide
+ */
+ String SHELL_COMMAND_CLEAR_NETWORK_TIME = "clear_network_time";
+
+ /**
* A shell command that injects a GNSS time suggestion.
* @hide
*/
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index 63f4bcf..d31124d 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -662,9 +662,7 @@
* @return the associations list
* @see #addOnAssociationsChangedListener(Executor, OnAssociationsChangedListener)
* @see #removeOnAssociationsChangedListener(OnAssociationsChangedListener)
- * @hide
*/
- @SystemApi
@UserHandleAware
@RequiresPermission(android.Manifest.permission.MANAGE_COMPANION_DEVICES)
public @NonNull List<AssociationInfo> getAllAssociations() {
@@ -678,10 +676,7 @@
/**
* Listener for any changes to {@link AssociationInfo}.
- *
- * @hide
*/
- @SystemApi
public interface OnAssociationsChangedListener {
/**
* Invoked when a change occurs to any of the associations for the user (including adding
@@ -696,9 +691,7 @@
* Register listener for any changes to {@link AssociationInfo}.
*
* @see #getAllAssociations()
- * @hide
*/
- @SystemApi
@UserHandleAware
@RequiresPermission(android.Manifest.permission.MANAGE_COMPANION_DEVICES)
public void addOnAssociationsChangedListener(
@@ -720,9 +713,7 @@
* Unregister listener for any changes to {@link AssociationInfo}.
*
* @see #getAllAssociations()
- * @hide
*/
- @SystemApi
@UserHandleAware
@RequiresPermission(android.Manifest.permission.MANAGE_COMPANION_DEVICES)
public void removeOnAssociationsChangedListener(
diff --git a/core/java/android/companion/virtual/TEST_MAPPING b/core/java/android/companion/virtual/TEST_MAPPING
new file mode 100644
index 0000000..6a67b7f
--- /dev/null
+++ b/core/java/android/companion/virtual/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "imports": [
+ {
+ "path": "frameworks/base/services/companion/java/com/android/server/companion/virtual"
+ }
+ ]
+}
diff --git a/core/java/android/content/BroadcastReceiver.java b/core/java/android/content/BroadcastReceiver.java
index c7a3b52..64dcc4d 100644
--- a/core/java/android/content/BroadcastReceiver.java
+++ b/core/java/android/content/BroadcastReceiver.java
@@ -82,6 +82,7 @@
final boolean mOrderedHint;
@UnsupportedAppUsage
final boolean mInitialStickyHint;
+ final boolean mAssumeDeliveredHint;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
final IBinder mToken;
@UnsupportedAppUsage
@@ -105,17 +106,38 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
public PendingResult(int resultCode, String resultData, Bundle resultExtras, int type,
boolean ordered, boolean sticky, IBinder token, int userId, int flags) {
+ this(resultCode, resultData, resultExtras, type, ordered, sticky,
+ guessAssumeDelivered(type, ordered), token, userId, flags);
+ }
+
+ /** @hide */
+ public PendingResult(int resultCode, String resultData, Bundle resultExtras, int type,
+ boolean ordered, boolean sticky, boolean assumeDelivered, IBinder token,
+ int userId, int flags) {
mResultCode = resultCode;
mResultData = resultData;
mResultExtras = resultExtras;
mType = type;
mOrderedHint = ordered;
mInitialStickyHint = sticky;
+ mAssumeDeliveredHint = assumeDelivered;
mToken = token;
mSendingUser = userId;
mFlags = flags;
}
+ /** @hide */
+ public static boolean guessAssumeDelivered(int type, boolean ordered) {
+ // When a caller didn't provide a concrete way of knowing if we need
+ // to report delivery, make a best-effort guess
+ if (type == TYPE_COMPONENT) {
+ return false;
+ } else if (ordered && type != TYPE_UNREGISTERED) {
+ return false;
+ }
+ return true;
+ }
+
/**
* Version of {@link BroadcastReceiver#setResultCode(int)
* BroadcastReceiver.setResultCode(int)} for
@@ -252,7 +274,7 @@
"Finishing broadcast to component " + mToken);
sendFinished(mgr);
}
- } else if (mOrderedHint && mType != TYPE_UNREGISTERED) {
+ } else {
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing broadcast to " + mToken);
final IActivityManager mgr = ActivityManager.getService();
@@ -279,13 +301,16 @@
if (mResultExtras != null) {
mResultExtras.setAllowFds(false);
}
- if (mOrderedHint) {
- am.finishReceiver(mToken, mResultCode, mResultData, mResultExtras,
- mAbortBroadcast, mFlags);
- } else {
- // This broadcast was sent to a component; it is not ordered,
- // but we still need to tell the activity manager we are done.
- am.finishReceiver(mToken, 0, null, null, false, mFlags);
+
+ // When the OS didn't assume delivery, we need to inform
+ // it that we've actually finished the delivery
+ if (!mAssumeDeliveredHint) {
+ if (mOrderedHint) {
+ am.finishReceiver(mToken, mResultCode, mResultData, mResultExtras,
+ mAbortBroadcast, mFlags);
+ } else {
+ am.finishReceiver(mToken, 0, null, null, false, mFlags);
+ }
}
} catch (RemoteException ex) {
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 879c8bd..c8d48c1 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -26,6 +26,8 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.PermissionMethod;
+import android.annotation.PermissionName;
import android.annotation.RequiresPermission;
import android.annotation.StringDef;
import android.annotation.StringRes;
@@ -53,8 +55,6 @@
import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
-import android.content.pm.PermissionMethod;
-import android.content.pm.PermissionName;
import android.content.res.AssetManager;
import android.content.res.ColorStateList;
import android.content.res.Configuration;
@@ -6859,6 +6859,26 @@
@CreatePackageOptions int flags) throws PackageManager.NameNotFoundException;
/**
+ * Creates a context given an {@link android.content.pm.ApplicationInfo}.
+ *
+ * Context created is for an sdk library that is being loaded in sdk sandbox.
+ *
+ * @param sdkInfo information regarding the sdk library being loaded.
+ *
+ * @throws PackageManager.NameNotFoundException if there is no application with
+ * the given package name.
+ * @throws SecurityException if caller is not a SdkSandbox process.
+ *
+ * @hide
+ */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @NonNull
+ public Context createContextForSdkInSandbox(@NonNull ApplicationInfo sdkInfo,
+ @CreatePackageOptions int flags) throws PackageManager.NameNotFoundException {
+ throw new RuntimeException("Not implemented. Must override in a subclass.");
+ }
+
+ /**
* Return a new Context object for the given split name. The new Context has a ClassLoader and
* Resources object that can access the split's and all of its dependencies' code/resources.
* Each call to this method returns a new instance of a Context object;
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 0dc4adc..e65e91c 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -1073,6 +1073,15 @@
/** @hide */
@Override
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @NonNull
+ public Context createContextForSdkInSandbox(@NonNull ApplicationInfo sdkInfo, int flags)
+ throws PackageManager.NameNotFoundException {
+ return mBase.createContextForSdkInSandbox(sdkInfo, flags);
+ }
+
+ /** @hide */
+ @Override
public Context createContextForSplit(String splitName)
throws PackageManager.NameNotFoundException {
return mBase.createContextForSplit(splitName);
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 7ee8f60..77cf49d 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3587,17 +3587,6 @@
public static final String ACTION_MEDIA_BUTTON = "android.intent.action.MEDIA_BUTTON";
/**
- * Broadcast action: Launch System output switcher. Includes a single extra field,
- * {@link #EXTRA_PACKAGE_NAME}, which specifies the package name of the calling app
- * so that the system can get the corresponding MediaSession for the output switcher.
- *
- * @see #EXTRA_PACKAGE_NAME
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_SHOW_OUTPUT_SWITCHER =
- "android.intent.action.SHOW_OUTPUT_SWITCHER";
-
- /**
* Broadcast Action: The "Camera Button" was pressed. Includes a single
* extra field, {@link #EXTRA_KEY_EVENT}, containing the key event that
* caused the broadcast.
@@ -11601,7 +11590,7 @@
private void toUriInner(StringBuilder uri, String scheme, String defAction,
String defPackage, int flags) {
if (scheme != null) {
- uri.append("scheme=").append(scheme).append(';');
+ uri.append("scheme=").append(Uri.encode(scheme)).append(';');
}
if (mAction != null && !mAction.equals(defAction)) {
uri.append("action=").append(Uri.encode(mAction)).append(';');
diff --git a/core/java/android/content/pm/IPackageInstallerSession.aidl b/core/java/android/content/pm/IPackageInstallerSession.aidl
index c9a5632..9c1318e 100644
--- a/core/java/android/content/pm/IPackageInstallerSession.aidl
+++ b/core/java/android/content/pm/IPackageInstallerSession.aidl
@@ -46,6 +46,8 @@
void commit(in IntentSender statusReceiver, boolean forTransferred);
void transfer(in String packageName);
void abandon();
+ void seal();
+ List<String> fetchPackageNames();
DataLoaderParamsParcel getDataLoaderParams();
void addFile(int location, String name, long lengthBytes, in byte[] metadata, in byte[] signature);
@@ -62,7 +64,7 @@
void requestUserPreapproval(in PackageInstaller.PreapprovalDetails details, in IntentSender statusReceiver);
- boolean isKeepApplicationEnabledSetting();
+ boolean isApplicationEnabledSettingPersistent();
boolean isRequestUpdateOwnership();
ParcelFileDescriptor getAppMetadataFd();
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 54ca1e5..0e37c87 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -214,6 +214,8 @@
@UnsupportedAppUsage
void setInstallerPackageName(in String targetPackage, in String installerPackageName);
+ void relinquishUpdateOwnership(in String targetPackage);
+
void setApplicationCategoryHint(String packageName, int categoryHint, String callerPackageName);
/** @deprecated rawr, don't call AIDL methods directly! */
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 812b5b3..0b74dd1 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -44,8 +44,11 @@
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.app.ActivityManager;
+import android.app.ActivityThread;
import android.app.AppGlobals;
import android.compat.annotation.UnsupportedAppUsage;
+import android.content.IIntentReceiver;
+import android.content.IIntentSender;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.PackageManager.DeleteFlags;
@@ -59,9 +62,11 @@
import android.icu.util.ULocale;
import android.net.Uri;
import android.os.Build;
+import android.os.Bundle;
import android.os.FileBridge;
import android.os.Handler;
import android.os.HandlerExecutor;
+import android.os.IBinder;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
@@ -226,8 +231,8 @@
* {@link #STATUS_PENDING_USER_ACTION}, {@link #STATUS_SUCCESS},
* {@link #STATUS_FAILURE}, {@link #STATUS_FAILURE_ABORTED},
* {@link #STATUS_FAILURE_BLOCKED}, {@link #STATUS_FAILURE_CONFLICT},
- * {@link #STATUS_FAILURE_INCOMPATIBLE}, {@link #STATUS_FAILURE_INVALID}, or
- * {@link #STATUS_FAILURE_STORAGE}.
+ * {@link #STATUS_FAILURE_INCOMPATIBLE}, {@link #STATUS_FAILURE_INVALID},
+ * {@link #STATUS_FAILURE_STORAGE}, or {@link #STATUS_FAILURE_TIMEOUT}.
* <p>
* More information about a status may be available through additional
* extras; see the individual status documentation for details.
@@ -441,6 +446,13 @@
public static final int STATUS_FAILURE_INCOMPATIBLE = 7;
/**
+ * The operation failed because it didn't complete within the specified timeout.
+ *
+ * @see #EXTRA_STATUS_MESSAGE
+ */
+ public static final int STATUS_FAILURE_TIMEOUT = 8;
+
+ /**
* Default value, non-streaming installation session.
*
* @see #EXTRA_DATA_LOADER_TYPE
@@ -1016,6 +1028,61 @@
}
/**
+ * Commit the session when all constraints are satisfied. This is a convenient method to
+ * combine {@link #waitForInstallConstraints(List, InstallConstraints, IntentSender, long)}
+ * and {@link Session#commit(IntentSender)}.
+ * <p>
+ * Once this method is called, the session is sealed and no additional mutations
+ * may be performed on the session. In the case of timeout, you may commit the
+ * session again using this method or {@link Session#commit(IntentSender)} for retries.
+ *
+ * @param statusReceiver Called when the state of the session changes. Intents
+ * sent to this receiver contain {@link #EXTRA_STATUS}.
+ * Refer to the individual status codes on how to handle them.
+ * @param constraints The requirements to satisfy before committing the session.
+ * @param timeoutMillis The maximum time to wait, in milliseconds until the
+ * constraints are satisfied. The caller will be notified via
+ * {@code statusReceiver} if timeout happens before commit.
+ */
+ public void commitSessionAfterInstallConstraintsAreMet(int sessionId,
+ @NonNull IntentSender statusReceiver, @NonNull InstallConstraints constraints,
+ @DurationMillisLong long timeoutMillis) {
+ try {
+ var session = mInstaller.openSession(sessionId);
+ session.seal();
+ var packageNames = session.fetchPackageNames();
+ var intentSender = new IntentSender((IIntentSender) new IIntentSender.Stub() {
+ @Override
+ public void send(int code, Intent intent, String resolvedType,
+ IBinder allowlistToken, IIntentReceiver finishedReceiver,
+ String requiredPermission, Bundle options) {
+ var result = intent.getParcelableExtra(
+ PackageInstaller.EXTRA_INSTALL_CONSTRAINTS_RESULT,
+ InstallConstraintsResult.class);
+ try {
+ if (result.isAllConstraintsSatisfied()) {
+ session.commit(statusReceiver, false);
+ } else {
+ // timeout
+ final Intent fillIn = new Intent();
+ fillIn.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
+ fillIn.putExtra(PackageInstaller.EXTRA_STATUS, STATUS_FAILURE_TIMEOUT);
+ fillIn.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE,
+ "Install constraints not satisfied within timeout");
+ statusReceiver.sendIntent(
+ ActivityThread.currentApplication(), 0, fillIn, null, null);
+ }
+ } catch (Exception ignore) {
+ }
+ }
+ });
+ waitForInstallConstraints(packageNames, constraints, intentSender, timeoutMillis);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Events for observing session lifecycle.
* <p>
* A typical session lifecycle looks like this:
@@ -1943,9 +2010,9 @@
* @return {@code true} if this session will keep the existing application enabled setting
* after installation.
*/
- public boolean isKeepApplicationEnabledSetting() {
+ public boolean isApplicationEnabledSettingPersistent() {
try {
- return mSession.isKeepApplicationEnabledSetting();
+ return mSession.isApplicationEnabledSettingPersistent();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2198,7 +2265,7 @@
/** {@hide} */
public int requireUserAction = USER_ACTION_UNSPECIFIED;
/** {@hide} */
- public boolean keepApplicationEnabledSetting = false;
+ public boolean applicationEnabledSettingPersistent = false;
/**
* Construct parameters for a new package install session.
@@ -2243,7 +2310,7 @@
rollbackDataPolicy = source.readInt();
requireUserAction = source.readInt();
packageSource = source.readInt();
- keepApplicationEnabledSetting = source.readBoolean();
+ applicationEnabledSettingPersistent = source.readBoolean();
}
/** {@hide} */
@@ -2274,7 +2341,7 @@
ret.rollbackDataPolicy = rollbackDataPolicy;
ret.requireUserAction = requireUserAction;
ret.packageSource = packageSource;
- ret.keepApplicationEnabledSetting = keepApplicationEnabledSetting;
+ ret.applicationEnabledSettingPersistent = applicationEnabledSettingPersistent;
return ret;
}
@@ -2772,8 +2839,8 @@
* Request to keep the original application enabled setting. This will prevent the
* application from being enabled if it was previously in a disabled state.
*/
- public void setKeepApplicationEnabledSetting() {
- this.keepApplicationEnabledSetting = true;
+ public void setApplicationEnabledSettingPersistent() {
+ this.applicationEnabledSettingPersistent = true;
}
/**
@@ -2828,7 +2895,8 @@
pw.printPair("requiredInstalledVersionCode", requiredInstalledVersionCode);
pw.printPair("dataLoaderParams", dataLoaderParams);
pw.printPair("rollbackDataPolicy", rollbackDataPolicy);
- pw.printPair("keepApplicationEnabledSetting", keepApplicationEnabledSetting);
+ pw.printPair("applicationEnabledSettingPersistent",
+ applicationEnabledSettingPersistent);
pw.println();
}
@@ -2869,7 +2937,7 @@
dest.writeInt(rollbackDataPolicy);
dest.writeInt(requireUserAction);
dest.writeInt(packageSource);
- dest.writeBoolean(keepApplicationEnabledSetting);
+ dest.writeBoolean(applicationEnabledSettingPersistent);
}
public static final Parcelable.Creator<SessionParams>
@@ -3072,7 +3140,7 @@
public boolean isPreapprovalRequested;
/** @hide */
- public boolean keepApplicationEnabledSetting;
+ public boolean applicationEnabledSettingPersistent;
/** @hide */
public int pendingUserActionReason;
@@ -3130,7 +3198,7 @@
requireUserAction = source.readInt();
installerUid = source.readInt();
packageSource = source.readInt();
- keepApplicationEnabledSetting = source.readBoolean();
+ applicationEnabledSettingPersistent = source.readBoolean();
pendingUserActionReason = source.readInt();
}
@@ -3665,8 +3733,8 @@
* Returns {@code true} if this session will keep the existing application enabled setting
* after installation.
*/
- public boolean isKeepApplicationEnabledSetting() {
- return keepApplicationEnabledSetting;
+ public boolean isApplicationEnabledSettingPersistent() {
+ return applicationEnabledSettingPersistent;
}
/**
@@ -3744,7 +3812,7 @@
dest.writeInt(requireUserAction);
dest.writeInt(installerUid);
dest.writeInt(packageSource);
- dest.writeBoolean(keepApplicationEnabledSetting);
+ dest.writeBoolean(applicationEnabledSettingPersistent);
dest.writeInt(pendingUserActionReason);
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index e49ea34..900454d 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1552,7 +1552,7 @@
*
* @hide
*/
- public static final int INSTALL_BYPASS_LOW_TARGET_SDK_BLOCK = 0x00800000;
+ public static final int INSTALL_BYPASS_LOW_TARGET_SDK_BLOCK = 0x01000000;
/**
* Flag parameter for {@link PackageInstaller.SessionParams} to indicate that the
@@ -10877,4 +10877,16 @@
throw new UnsupportedOperationException(
"isShowNewAppInstalledNotificationEnabled not implemented in subclass");
}
+
+ /**
+ * Attempt to relinquish the update ownership of the given package. Only the current
+ * update owner of the given package can use this API or a SecurityException will be
+ * thrown.
+ *
+ * @param targetPackage The installed package whose update owner will be changed.
+ */
+ public void relinquishUpdateOwnership(@NonNull String targetPackage) {
+ throw new UnsupportedOperationException(
+ "relinquishUpdateOwnership not implemented in subclass");
+ }
}
diff --git a/core/java/android/content/pm/PermissionMethod.java b/core/java/android/content/pm/PermissionMethod.java
deleted file mode 100644
index 647c696..0000000
--- a/core/java/android/content/pm/PermissionMethod.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.pm;
-
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.RetentionPolicy.CLASS;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * Documents that the subject method's job is to look
- * up whether the provided or calling uid/pid has the requested permission.
- *
- * <p>Methods should either return `void`, but potentially throw {@link SecurityException},
- * or return {@link android.content.pm.PackageManager.PermissionResult} `int`.
- *
- * @hide
- */
-@Retention(CLASS)
-@Target({METHOD})
-public @interface PermissionMethod {
- /**
- * Hard-coded list of permissions checked by this method
- */
- @PermissionName String[] value() default {};
- /**
- * If true, the check passes if the caller
- * has any ONE of the supplied permissions
- */
- boolean anyOf() default false;
- /**
- * Signifies that the permission check passes if
- * the calling process OR the current process has
- * the permission
- */
- boolean orSelf() default false;
-}
diff --git a/core/java/android/content/pm/PermissionName.java b/core/java/android/content/pm/PermissionName.java
deleted file mode 100644
index 719e13b..0000000
--- a/core/java/android/content/pm/PermissionName.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.pm;
-
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.ElementType.PARAMETER;
-import static java.lang.annotation.RetentionPolicy.CLASS;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * Denotes that the annotated {@link String} represents a permission name.
- *
- * @hide
- */
-@Retention(CLASS)
-@Target({PARAMETER, METHOD, LOCAL_VARIABLE, FIELD})
-public @interface PermissionName {}
diff --git a/core/java/android/content/pm/ResolveInfo.java b/core/java/android/content/pm/ResolveInfo.java
index 6f07dd7..f900440 100644
--- a/core/java/android/content/pm/ResolveInfo.java
+++ b/core/java/android/content/pm/ResolveInfo.java
@@ -16,6 +16,7 @@
package android.content.pm;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
@@ -107,6 +108,14 @@
public int match;
/**
+ * UserHandle of originating user for ResolveInfo. This will help caller distinguish cross
+ * profile results from intent resolution.
+ * @hide
+ */
+ @Nullable
+ public UserHandle userHandle;
+
+ /**
* Only set when returned by
* {@link PackageManager#queryIntentActivityOptions}, this tells you
* which of the given specific intents this result came from. 0 is the
@@ -418,6 +427,7 @@
handleAllWebDataURI = orig.handleAllWebDataURI;
mAutoResolutionAllowed = orig.mAutoResolutionAllowed;
isInstantAppAvailable = orig.isInstantAppAvailable;
+ userHandle = orig.userHandle;
}
public String toString() {
@@ -441,6 +451,10 @@
sb.append(" targetUserId=");
sb.append(targetUserId);
}
+
+ sb.append(" userHandle=");
+ sb.append(userHandle);
+
sb.append('}');
return sb.toString();
}
@@ -483,6 +497,7 @@
dest.writeInt(handleAllWebDataURI ? 1 : 0);
dest.writeInt(mAutoResolutionAllowed ? 1 : 0);
dest.writeInt(isInstantAppAvailable ? 1 : 0);
+ dest.writeInt(userHandle != null ? userHandle.getIdentifier() : UserHandle.USER_CURRENT);
}
public static final @android.annotation.NonNull Creator<ResolveInfo> CREATOR
@@ -532,6 +547,10 @@
handleAllWebDataURI = source.readInt() != 0;
mAutoResolutionAllowed = source.readInt() != 0;
isInstantAppAvailable = source.readInt() != 0;
+ int userHandleId = source.readInt();
+ if (userHandleId != UserHandle.USER_CURRENT) {
+ userHandle = UserHandle.of(userHandleId);
+ }
}
public static class DisplayNameComparator
diff --git a/core/java/android/content/pm/ServiceInfo.java b/core/java/android/content/pm/ServiceInfo.java
index 4ade8a8..0b503eb 100644
--- a/core/java/android/content/pm/ServiceInfo.java
+++ b/core/java/android/content/pm/ServiceInfo.java
@@ -133,20 +133,15 @@
* Data(photo, file, account) upload/download, backup/restore, import/export, fetch,
* transfer over network between device and cloud.
*
- * <p>Apps targeting API level {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} and
- * later should NOT use this type:
- * calling {@link android.app.Service#startForeground(int, android.app.Notification, int)} with
- * this type on devices running {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} is still
- * allowed, but calling it with this type on devices running future platform releases may get a
- * {@link android.app.InvalidForegroundServiceTypeException}.</p>
- *
- * @deprecated Use {@link android.app.job.JobInfo.Builder} data transfer APIs instead.
+ * <p class="note">
+ * Use the {@link android.app.job.JobInfo.Builder#setDataTransfer} API for data transfers
+ * that can be deferred until conditions are ideal for the app or device.
+ * </p>
*/
@RequiresPermission(
value = Manifest.permission.FOREGROUND_SERVICE_DATA_SYNC,
conditional = true
)
- @Deprecated
public static final int FOREGROUND_SERVICE_TYPE_DATA_SYNC = 1 << 0;
/**
@@ -219,12 +214,15 @@
* {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} and later, will require permission
* {@link android.Manifest.permission#FOREGROUND_SERVICE_CONNECTED_DEVICE} and one of the
* following permissions:
+ * {@link android.Manifest.permission#BLUETOOTH_ADVERTISE},
* {@link android.Manifest.permission#BLUETOOTH_CONNECT},
+ * {@link android.Manifest.permission#BLUETOOTH_SCAN},
* {@link android.Manifest.permission#CHANGE_NETWORK_STATE},
* {@link android.Manifest.permission#CHANGE_WIFI_STATE},
* {@link android.Manifest.permission#CHANGE_WIFI_MULTICAST_STATE},
* {@link android.Manifest.permission#NFC},
* {@link android.Manifest.permission#TRANSMIT_IR},
+ * {@link android.Manifest.permission#UWB_RANGING},
* or has been granted the access to one of the attached USB devices/accessories.
*/
@RequiresPermission(
@@ -232,12 +230,15 @@
Manifest.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE,
},
anyOf = {
+ Manifest.permission.BLUETOOTH_ADVERTISE,
Manifest.permission.BLUETOOTH_CONNECT,
+ Manifest.permission.BLUETOOTH_SCAN,
Manifest.permission.CHANGE_NETWORK_STATE,
Manifest.permission.CHANGE_WIFI_STATE,
Manifest.permission.CHANGE_WIFI_MULTICAST_STATE,
Manifest.permission.NFC,
Manifest.permission.TRANSMIT_IR,
+ Manifest.permission.UWB_RANGING,
},
conditional = true
)
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index 2be0323..44747fa 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -171,6 +171,16 @@
public static final int FLAG_MAIN = 0x00004000;
/**
+ * Indicates that this user was created for the purposes of testing.
+ *
+ * <p>These users are subject to removal during tests and should not be used on actual devices
+ * used by humans.
+ *
+ * @hide
+ */
+ public static final int FLAG_FOR_TESTING = 0x00008000;
+
+ /**
* @hide
*/
@IntDef(flag = true, prefix = "FLAG_", value = {
@@ -188,7 +198,8 @@
FLAG_SYSTEM,
FLAG_PROFILE,
FLAG_EPHEMERAL_ON_CREATE,
- FLAG_MAIN
+ FLAG_MAIN,
+ FLAG_FOR_TESTING
})
@Retention(RetentionPolicy.SOURCE)
public @interface UserInfoFlag {
@@ -369,6 +380,12 @@
return (flags & FLAG_EPHEMERAL) == FLAG_EPHEMERAL;
}
+ /** @hide */
+ @TestApi
+ public boolean isForTesting() {
+ return (flags & FLAG_FOR_TESTING) == FLAG_FOR_TESTING;
+ }
+
public boolean isInitialized() {
return (flags & FLAG_INITIALIZED) == FLAG_INITIALIZED;
}
diff --git a/core/java/android/credentials/GetCredentialResponse.java b/core/java/android/credentials/GetCredentialResponse.java
index 576da8b..4f8b026 100644
--- a/core/java/android/credentials/GetCredentialResponse.java
+++ b/core/java/android/credentials/GetCredentialResponse.java
@@ -19,7 +19,6 @@
import static java.util.Objects.requireNonNull;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
@@ -33,14 +32,14 @@
/**
* The credential that can be used to authenticate the user.
*/
- @Nullable
+ @NonNull
private final Credential mCredential;
/**
* Returns the credential that can be used to authenticate the user, or {@code null} if no
* credential is available.
*/
- @Nullable
+ @NonNull
public Credential getCredential() {
return mCredential;
}
@@ -69,13 +68,6 @@
mCredential = requireNonNull(credential, "credential must not be null");
}
- /**
- * Constructs a {@link GetCredentialResponse}.
- */
- public GetCredentialResponse() {
- mCredential = null;
- }
-
private GetCredentialResponse(@NonNull Parcel in) {
Credential credential = in.readTypedObject(Credential.CREATOR);
mCredential = credential;
diff --git a/core/java/android/credentials/ui/Entry.java b/core/java/android/credentials/ui/Entry.java
index 9f2edae..37a5724 100644
--- a/core/java/android/credentials/ui/Entry.java
+++ b/core/java/android/credentials/ui/Entry.java
@@ -88,6 +88,7 @@
/** Constructor to be used for an entry that requires a pending intent to be invoked
* when clicked.
*/
+ // TODO: Remove this constructor as it is no longer used
public Entry(@NonNull String key, @NonNull String subkey, @NonNull Slice slice,
@NonNull PendingIntent pendingIntent, @NonNull Intent intent) {
this(key, subkey, slice);
diff --git a/core/java/android/database/sqlite/SQLiteBindOrColumnIndexOutOfRangeException.java b/core/java/android/database/sqlite/SQLiteBindOrColumnIndexOutOfRangeException.java
index 41f2f9c..b86b97c 100644
--- a/core/java/android/database/sqlite/SQLiteBindOrColumnIndexOutOfRangeException.java
+++ b/core/java/android/database/sqlite/SQLiteBindOrColumnIndexOutOfRangeException.java
@@ -17,7 +17,7 @@
package android.database.sqlite;
/**
- * Thrown if the the bind or column parameter index is out of range
+ * Thrown if the bind or column parameter index is out of range.
*/
public class SQLiteBindOrColumnIndexOutOfRangeException extends SQLiteException {
public SQLiteBindOrColumnIndexOutOfRangeException() {}
diff --git a/core/java/android/database/sqlite/SQLiteDiskIOException.java b/core/java/android/database/sqlite/SQLiteDiskIOException.java
index 01b2069..152d90a 100644
--- a/core/java/android/database/sqlite/SQLiteDiskIOException.java
+++ b/core/java/android/database/sqlite/SQLiteDiskIOException.java
@@ -17,7 +17,7 @@
package android.database.sqlite;
/**
- * An exception that indicates that an IO error occured while accessing the
+ * Indicates that an IO error occurred while accessing the
* SQLite database file.
*/
public class SQLiteDiskIOException extends SQLiteException {
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index c716f319..81d6ba9 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -24,7 +24,6 @@
import android.annotation.SdkConstant.SdkConstantType;
import android.app.ActivityThread;
import android.app.AppOpsManager;
-import android.app.compat.CompatChanges;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.ImageFormat;
@@ -42,7 +41,6 @@
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.SystemProperties;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RSIllegalArgumentException;
@@ -279,14 +277,6 @@
*/
public native static int getNumberOfCameras();
- private static final boolean sLandscapeToPortrait =
- SystemProperties.getBoolean(CameraManager.LANDSCAPE_TO_PORTRAIT_PROP, false);
-
- private static boolean shouldOverrideToPortrait() {
- return CompatChanges.isChangeEnabled(CameraManager.OVERRIDE_FRONT_CAMERA_APP_COMPAT)
- && sLandscapeToPortrait;
- }
-
/**
* Returns the information about a particular camera.
* If {@link #getNumberOfCameras()} returns N, the valid id is 0 to N-1.
@@ -296,7 +286,8 @@
* low-level failure).
*/
public static void getCameraInfo(int cameraId, CameraInfo cameraInfo) {
- boolean overrideToPortrait = shouldOverrideToPortrait();
+ boolean overrideToPortrait = CameraManager.shouldOverrideToPortrait(
+ ActivityThread.currentApplication().getApplicationContext());
_getCameraInfo(cameraId, overrideToPortrait, cameraInfo);
IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
@@ -493,7 +484,8 @@
mEventHandler = null;
}
- boolean overrideToPortrait = shouldOverrideToPortrait();
+ boolean overrideToPortrait = CameraManager.shouldOverrideToPortrait(
+ ActivityThread.currentApplication().getApplicationContext());
return native_setup(new WeakReference<Camera>(this), cameraId,
ActivityThread.currentOpPackageName(), overrideToPortrait);
}
diff --git a/core/java/android/hardware/camera2/CameraExtensionSession.java b/core/java/android/hardware/camera2/CameraExtensionSession.java
index 1542d61..21fead9 100644
--- a/core/java/android/hardware/camera2/CameraExtensionSession.java
+++ b/core/java/android/hardware/camera2/CameraExtensionSession.java
@@ -19,10 +19,7 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.hardware.camera2.impl.PublicKey;
-import android.hardware.camera2.utils.TypeReference;
-import android.util.Pair;
-import android.util.Range;
+import android.hardware.camera2.utils.HashCodeHelpers;
import java.util.concurrent.Executor;
@@ -434,14 +431,66 @@
}
/**
- * Return the realtime still {@link #capture} latency.
+ * Realtime calculated still {@link #capture} latency.
*
- * <p>The pair will be in milliseconds with the first value indicating the capture latency from
- * the {@link ExtensionCaptureCallback#onCaptureStarted} until
- * {@link ExtensionCaptureCallback#onCaptureProcessStarted}
- * and the second value containing the estimated post-processing latency from
- * {@link ExtensionCaptureCallback#onCaptureProcessStarted} until the processed frame returns
- * to the client.</p>
+ * @see #getRealtimeStillCaptureLatency()
+ */
+ public final static class StillCaptureLatency {
+ private final long mCaptureLatency, mProcessingLatency;
+
+ public StillCaptureLatency(long captureLatency, long processingLatency) {
+ mCaptureLatency = captureLatency;
+ mProcessingLatency = processingLatency;
+ }
+ /**
+ * Return the capture latency from
+ * {@link ExtensionCaptureCallback#onCaptureStarted} until
+ * {@link ExtensionCaptureCallback#onCaptureProcessStarted}.
+ *
+ * @return The realtime capture latency in milliseconds.
+ */
+ public long getCaptureLatency() {
+ return mCaptureLatency;
+ }
+
+ /**
+ * Return the estimated post-processing latency from
+ * {@link ExtensionCaptureCallback#onCaptureProcessStarted} until the processed frame
+ * returns to the client.
+ *
+ * @return returns post-processing latency in milliseconds
+ */
+ public long getProcessingLatency() {
+ return mProcessingLatency;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ StillCaptureLatency latency = (StillCaptureLatency) o;
+
+ if (mCaptureLatency != latency.mCaptureLatency) return false;
+ if (mProcessingLatency != latency.mProcessingLatency) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return HashCodeHelpers.hashCode(mCaptureLatency, mProcessingLatency);
+ }
+
+ @Override
+ public String toString() {
+ return "StillCaptureLatency(processingLatency:" + mProcessingLatency +
+ ", captureLatency: " + mCaptureLatency + ")";
+ }
+ }
+
+ /**
+ * Return the realtime still {@link #capture} latency.
*
* <p>The estimations will take into account the current environment conditions, the camera
* state and will include the time spent processing the multi-frame capture request along with
@@ -451,7 +500,7 @@
* or {@code null} if the estimation is not supported.
*/
@Nullable
- public Pair<Long, Long> getRealtimeStillCaptureLatency() throws CameraAccessException {
+ public StillCaptureLatency getRealtimeStillCaptureLatency() throws CameraAccessException {
throw new UnsupportedOperationException("Subclasses must override this method");
}
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 5b6e288..da847a8 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -115,7 +115,14 @@
@Overridable
@EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.BASE)
@TestApi
- public static final long OVERRIDE_FRONT_CAMERA_APP_COMPAT = 250678880L;
+ public static final long OVERRIDE_CAMERA_LANDSCAPE_TO_PORTRAIT = 250678880L;
+
+ /**
+ * Package-level opt in/out for the above.
+ * @hide
+ */
+ public static final String PROPERTY_COMPAT_OVERRIDE_LANDSCAPE_TO_PORTRAIT =
+ "android.camera.PROPERTY_COMPAT_OVERRIDE_LANDSCAPE_TO_PORTRAIT";
/**
* System property for allowing the above
@@ -391,6 +398,23 @@
* except that it uses {@link java.util.concurrent.Executor} as an argument
* instead of {@link android.os.Handler}.</p>
*
+ * <p>Note: If the order between some availability callbacks matters, the implementation of the
+ * executor should handle those callbacks in the same thread to maintain the callbacks' order.
+ * Some examples are:</p>
+ *
+ * <ul>
+ *
+ * <li>{@link AvailabilityCallback#onCameraAvailable} and
+ * {@link AvailabilityCallback#onCameraUnavailable} of the same camera ID.</li>
+ *
+ * <li>{@link AvailabilityCallback#onCameraAvailable} or
+ * {@link AvailabilityCallback#onCameraUnavailable} of a logical multi-camera, and {@link
+ * AvailabilityCallback#onPhysicalCameraUnavailable} or
+ * {@link AvailabilityCallback#onPhysicalCameraAvailable} of its physical
+ * cameras.</li>
+ *
+ * </ul>
+ *
* @param executor The executor which will be used to invoke the callback.
* @param callback the new callback to send camera availability notices to
*
@@ -607,7 +631,7 @@
try {
Size displaySize = getDisplaySize();
- boolean overrideToPortrait = shouldOverrideToPortrait();
+ boolean overrideToPortrait = shouldOverrideToPortrait(mContext);
CameraMetadataNative info = cameraService.getCameraCharacteristics(cameraId,
mContext.getApplicationInfo().targetSdkVersion, overrideToPortrait);
try {
@@ -727,7 +751,7 @@
"Camera service is currently unavailable");
}
- boolean overrideToPortrait = shouldOverrideToPortrait();
+ boolean overrideToPortrait = shouldOverrideToPortrait(mContext);
cameraUser = cameraService.connectDevice(callbacks, cameraId,
mContext.getOpPackageName(), mContext.getAttributionTag(), uid,
oomScoreOffset, mContext.getApplicationInfo().targetSdkVersion,
@@ -1159,9 +1183,26 @@
return CameraManagerGlobal.get().getTorchStrengthLevel(cameraId);
}
- private static boolean shouldOverrideToPortrait() {
- return CompatChanges.isChangeEnabled(OVERRIDE_FRONT_CAMERA_APP_COMPAT)
- && CameraManagerGlobal.sLandscapeToPortrait;
+ /**
+ * @hide
+ */
+ public static boolean shouldOverrideToPortrait(@Nullable Context context) {
+ if (!CameraManagerGlobal.sLandscapeToPortrait) {
+ return false;
+ }
+
+ if (context != null) {
+ PackageManager packageManager = context.getPackageManager();
+
+ try {
+ return packageManager.getProperty(context.getOpPackageName(),
+ PROPERTY_COMPAT_OVERRIDE_LANDSCAPE_TO_PORTRAIT).getBoolean();
+ } catch (PackageManager.NameNotFoundException e) {
+ // No such property
+ }
+ }
+
+ return CompatChanges.isChangeEnabled(OVERRIDE_CAMERA_LANDSCAPE_TO_PORTRAIT);
}
/**
@@ -2318,6 +2359,15 @@
final AvailabilityCallback callback = mCallbackMap.keyAt(i);
postSingleUpdate(callback, executor, id, null /*physicalId*/, status);
+
+ // Send the NOT_PRESENT state for unavailable physical cameras
+ if (isAvailable(status) && mUnavailablePhysicalDevices.containsKey(id)) {
+ ArrayList<String> unavailableIds = mUnavailablePhysicalDevices.get(id);
+ for (String unavailableId : unavailableIds) {
+ postSingleUpdate(callback, executor, id, unavailableId,
+ ICameraServiceListener.STATUS_NOT_PRESENT);
+ }
+ }
}
} // onStatusChangedLocked
diff --git a/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java
index 9437ea7..709fa60 100644
--- a/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java
@@ -361,7 +361,7 @@
}
@Override
- public Pair<Long, Long> getRealtimeStillCaptureLatency() throws CameraAccessException {
+ public StillCaptureLatency getRealtimeStillCaptureLatency() throws CameraAccessException {
synchronized (mInterfaceLock) {
if (!mInitialized) {
throw new IllegalStateException("Uninitialized component");
@@ -370,7 +370,7 @@
try {
LatencyPair latency = mSessionProcessor.getRealtimeCaptureLatency();
if (latency != null) {
- return new Pair<>(latency.first, latency.second);
+ return new StillCaptureLatency(latency.first, latency.second);
}
return null;
diff --git a/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java
index ed48a6d..3f85d44 100644
--- a/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java
@@ -513,7 +513,7 @@
}
@Override
- public Pair<Long, Long> getRealtimeStillCaptureLatency() throws CameraAccessException {
+ public StillCaptureLatency getRealtimeStillCaptureLatency() throws CameraAccessException {
synchronized (mInterfaceLock) {
if (!mInitialized) {
throw new IllegalStateException("Uninitialized component");
@@ -522,7 +522,7 @@
try {
LatencyPair latency = mImageExtender.getRealtimeCaptureLatency();
if (latency != null) {
- return new Pair<>(latency.first, latency.second);
+ return new StillCaptureLatency(latency.first, latency.second);
}
return null;
diff --git a/core/java/android/hardware/devicestate/DeviceStateManager.java b/core/java/android/hardware/devicestate/DeviceStateManager.java
index dba1a5e..6a667fe 100644
--- a/core/java/android/hardware/devicestate/DeviceStateManager.java
+++ b/core/java/android/hardware/devicestate/DeviceStateManager.java
@@ -251,6 +251,10 @@
@Nullable
private Boolean lastResult;
+ public FoldStateListener(Context context) {
+ this(context, folded -> {});
+ }
+
public FoldStateListener(Context context, Consumer<Boolean> listener) {
mFoldedDeviceStates = context.getResources().getIntArray(
com.android.internal.R.array.config_foldedDeviceStates);
@@ -266,5 +270,10 @@
mDelegate.accept(folded);
}
}
+
+ @Nullable
+ public Boolean getFolded() {
+ return lastResult;
+ }
}
}
diff --git a/core/java/android/hardware/face/IFaceService.aidl b/core/java/android/hardware/face/IFaceService.aidl
index 2bf187a..5fcc31e 100644
--- a/core/java/android/hardware/face/IFaceService.aidl
+++ b/core/java/android/hardware/face/IFaceService.aidl
@@ -43,7 +43,7 @@
byte[] dumpSensorServiceStateProto(int sensorId, boolean clearSchedulerBuffer);
// Retrieve static sensor properties for all face sensors
- @EnforcePermission("MANAGE_BIOMETRIC")
+ @EnforcePermission("USE_BIOMETRIC_INTERNAL")
List<FaceSensorPropertiesInternal> getSensorPropertiesInternal(String opPackageName);
// Retrieve static sensor properties for the specified sensor
diff --git a/core/java/android/hardware/input/KeyboardLayout.java b/core/java/android/hardware/input/KeyboardLayout.java
index 58f7759..0311da4 100644
--- a/core/java/android/hardware/input/KeyboardLayout.java
+++ b/core/java/android/hardware/input/KeyboardLayout.java
@@ -23,6 +23,7 @@
import java.util.HashMap;
import java.util.Map;
+import java.util.Objects;
/**
* Describes a keyboard layout.
@@ -30,6 +31,37 @@
* @hide
*/
public final class KeyboardLayout implements Parcelable, Comparable<KeyboardLayout> {
+
+ /** Undefined keyboard layout */
+ public static final String LAYOUT_TYPE_UNDEFINED = "undefined";
+
+ /** Qwerty-based keyboard layout */
+ public static final String LAYOUT_TYPE_QWERTY = "qwerty";
+
+ /** Qwertz-based keyboard layout */
+ public static final String LAYOUT_TYPE_QWERTZ = "qwertz";
+
+ /** Azerty-based keyboard layout */
+ public static final String LAYOUT_TYPE_AZERTY = "azerty";
+
+ /** Dvorak keyboard layout */
+ public static final String LAYOUT_TYPE_DVORAK = "dvorak";
+
+ /** Colemak keyboard layout */
+ public static final String LAYOUT_TYPE_COLEMAK = "colemak";
+
+ /** Workman keyboard layout */
+ public static final String LAYOUT_TYPE_WORKMAN = "workman";
+
+ /** Turkish-F keyboard layout */
+ public static final String LAYOUT_TYPE_TURKISH_F = "turkish_f";
+
+ /** Turkish-Q keyboard layout */
+ public static final String LAYOUT_TYPE_TURKISH_Q = "turkish_q";
+
+ /** Keyboard layout that has been enhanced with a large number of extra characters */
+ public static final String LAYOUT_TYPE_EXTENDED = "extended";
+
private final String mDescriptor;
private final String mLabel;
private final String mCollection;
@@ -42,31 +74,24 @@
/** Currently supported Layout types in the KCM files */
private enum LayoutType {
- UNDEFINED(0, "undefined"),
- QWERTY(1, "qwerty"),
- QWERTZ(2, "qwertz"),
- AZERTY(3, "azerty"),
- DVORAK(4, "dvorak"),
- COLEMAK(5, "colemak"),
- WORKMAN(6, "workman"),
- TURKISH_F(7, "turkish_f"),
- TURKISH_Q(8, "turkish_q"),
- EXTENDED(9, "extended");
+ UNDEFINED(0, LAYOUT_TYPE_UNDEFINED),
+ QWERTY(1, LAYOUT_TYPE_QWERTY),
+ QWERTZ(2, LAYOUT_TYPE_QWERTZ),
+ AZERTY(3, LAYOUT_TYPE_AZERTY),
+ DVORAK(4, LAYOUT_TYPE_DVORAK),
+ COLEMAK(5, LAYOUT_TYPE_COLEMAK),
+ WORKMAN(6, LAYOUT_TYPE_WORKMAN),
+ TURKISH_F(7, LAYOUT_TYPE_TURKISH_F),
+ TURKISH_Q(8, LAYOUT_TYPE_TURKISH_Q),
+ EXTENDED(9, LAYOUT_TYPE_EXTENDED);
private final int mValue;
private final String mName;
private static final Map<Integer, LayoutType> VALUE_TO_ENUM_MAP = new HashMap<>();
static {
- VALUE_TO_ENUM_MAP.put(UNDEFINED.mValue, UNDEFINED);
- VALUE_TO_ENUM_MAP.put(QWERTY.mValue, QWERTY);
- VALUE_TO_ENUM_MAP.put(QWERTZ.mValue, QWERTZ);
- VALUE_TO_ENUM_MAP.put(AZERTY.mValue, AZERTY);
- VALUE_TO_ENUM_MAP.put(DVORAK.mValue, DVORAK);
- VALUE_TO_ENUM_MAP.put(COLEMAK.mValue, COLEMAK);
- VALUE_TO_ENUM_MAP.put(WORKMAN.mValue, WORKMAN);
- VALUE_TO_ENUM_MAP.put(TURKISH_F.mValue, TURKISH_F);
- VALUE_TO_ENUM_MAP.put(TURKISH_Q.mValue, TURKISH_Q);
- VALUE_TO_ENUM_MAP.put(EXTENDED.mValue, EXTENDED);
+ for (LayoutType type : LayoutType.values()) {
+ VALUE_TO_ENUM_MAP.put(type.mValue, type);
+ }
}
private static LayoutType of(int value) {
@@ -207,6 +232,9 @@
// keyboards to be listed before lower priority keyboards.
int result = Integer.compare(another.mPriority, mPriority);
if (result == 0) {
+ result = Integer.compare(mLayoutType.mValue, another.mLayoutType.mValue);
+ }
+ if (result == 0) {
result = mLabel.compareToIgnoreCase(another.mLabel);
}
if (result == 0) {
@@ -226,4 +254,21 @@
+ ", vendorId: " + mVendorId
+ ", productId: " + mProductId;
}
+
+ /**
+ * Check if the provided layout type is supported/valid.
+ *
+ * @param layoutName name of layout type
+ * @return {@code true} if the provided layout type is supported/valid.
+ */
+ public static boolean isLayoutTypeValid(@NonNull String layoutName) {
+ Objects.requireNonNull(layoutName, "Provided layout name should not be null");
+ for (LayoutType layoutType : LayoutType.values()) {
+ if (layoutName.equals(layoutType.getName())) {
+ return true;
+ }
+ }
+ // Layout doesn't match any supported layout types
+ return false;
+ }
}
diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java
index d55367f..ed6a88f 100644
--- a/core/java/android/inputmethodservice/IInputMethodWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java
@@ -223,11 +223,13 @@
final SomeArgs args = (SomeArgs) msg.obj;
final ImeTracker.Token statsToken = (ImeTracker.Token) args.arg3;
if (isValid(inputMethod, target, "DO_SHOW_SOFT_INPUT")) {
- ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH);
+ ImeTracker.forLogging().onProgress(
+ statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH);
inputMethod.showSoftInputWithToken(
msg.arg1, (ResultReceiver) args.arg2, (IBinder) args.arg1, statsToken);
} else {
- ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH);
+ ImeTracker.forLogging().onFailed(
+ statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH);
}
args.recycle();
return;
@@ -236,11 +238,13 @@
final SomeArgs args = (SomeArgs) msg.obj;
final ImeTracker.Token statsToken = (ImeTracker.Token) args.arg3;
if (isValid(inputMethod, target, "DO_HIDE_SOFT_INPUT")) {
- ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH);
+ ImeTracker.forLogging().onProgress(
+ statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH);
inputMethod.hideSoftInputWithToken(msg.arg1, (ResultReceiver) args.arg2,
(IBinder) args.arg1, statsToken);
} else {
- ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH);
+ ImeTracker.forLogging().onFailed(
+ statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH);
}
args.recycle();
return;
@@ -428,7 +432,7 @@
@Override
public void showSoftInput(IBinder showInputToken, @Nullable ImeTracker.Token statsToken,
int flags, ResultReceiver resultReceiver) {
- ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_IME_WRAPPER);
+ ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_IME_WRAPPER);
mCaller.executeOrSendMessage(mCaller.obtainMessageIOOO(DO_SHOW_SOFT_INPUT,
flags, showInputToken, resultReceiver, statsToken));
}
@@ -437,7 +441,7 @@
@Override
public void hideSoftInput(IBinder hideInputToken, @Nullable ImeTracker.Token statsToken,
int flags, ResultReceiver resultReceiver) {
- ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_IME_WRAPPER);
+ ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_IME_WRAPPER);
mCaller.executeOrSendMessage(mCaller.obtainMessageIOOO(DO_HIDE_SOFT_INPUT,
flags, hideInputToken, resultReceiver, statsToken));
}
diff --git a/core/java/android/inputmethodservice/IRemoteInputConnectionInvoker.java b/core/java/android/inputmethodservice/IRemoteInputConnectionInvoker.java
index 8759a6a..8e6f6dc 100644
--- a/core/java/android/inputmethodservice/IRemoteInputConnectionInvoker.java
+++ b/core/java/android/inputmethodservice/IRemoteInputConnectionInvoker.java
@@ -767,20 +767,20 @@
/**
* Invokes {@link IRemoteInputConnection#requestTextBoundsInfo(InputConnectionCommandHeader,
* RectF, ResultReceiver)}
- * @param rectF {@code rectF} parameter to be passed.
+ * @param bounds {@code rectF} parameter to be passed.
* @param executor {@code Executor} parameter to be passed.
* @param consumer {@code Consumer} parameter to be passed.
*/
@AnyThread
public void requestTextBoundsInfo(
- @NonNull RectF rectF, @NonNull @CallbackExecutor Executor executor,
+ @NonNull RectF bounds, @NonNull @CallbackExecutor Executor executor,
@NonNull Consumer<TextBoundsInfoResult> consumer) {
Objects.requireNonNull(executor);
Objects.requireNonNull(consumer);
final ResultReceiver resultReceiver = new TextBoundsInfoResultReceiver(executor, consumer);
try {
- mConnection.requestTextBoundsInfo(createHeader(), rectF, resultReceiver);
+ mConnection.requestTextBoundsInfo(createHeader(), bounds, resultReceiver);
} catch (RemoteException e) {
executor.execute(() -> consumer.accept(new TextBoundsInfoResult(CODE_CANCELLED)));
}
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 872414a..ee9d8a4 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -896,7 +896,8 @@
@MainThread
@Override
public void hideSoftInput(int flags, ResultReceiver resultReceiver) {
- ImeTracker.get().onProgress(mCurStatsToken, ImeTracker.PHASE_IME_HIDE_SOFT_INPUT);
+ ImeTracker.forLogging().onProgress(
+ mCurStatsToken, ImeTracker.PHASE_IME_HIDE_SOFT_INPUT);
if (DEBUG) Log.v(TAG, "hideSoftInput()");
if (getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.R
&& !mSystemCallingHideSoftInput) {
@@ -950,7 +951,8 @@
@MainThread
@Override
public void showSoftInput(int flags, ResultReceiver resultReceiver) {
- ImeTracker.get().onProgress(mCurStatsToken, ImeTracker.PHASE_IME_SHOW_SOFT_INPUT);
+ ImeTracker.forLogging().onProgress(
+ mCurStatsToken, ImeTracker.PHASE_IME_SHOW_SOFT_INPUT);
if (DEBUG) Log.v(TAG, "showSoftInput()");
// TODO(b/148086656): Disallow IME developers from calling InputMethodImpl methods.
if (getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.R
@@ -966,11 +968,11 @@
null /* icProto */);
final boolean wasVisible = isInputViewShown();
if (dispatchOnShowInputRequested(flags, false)) {
- ImeTracker.get().onProgress(mCurStatsToken,
+ ImeTracker.forLogging().onProgress(mCurStatsToken,
ImeTracker.PHASE_IME_ON_SHOW_SOFT_INPUT_TRUE);
showWindow(true);
} else {
- ImeTracker.get().onFailed(mCurStatsToken,
+ ImeTracker.forLogging().onFailed(mCurStatsToken,
ImeTracker.PHASE_IME_ON_SHOW_SOFT_INPUT_TRUE);
}
setImeWindowStatus(mapToImeWindowStatus(), mBackDisposition);
@@ -2979,7 +2981,7 @@
ImeTracing.getInstance().triggerServiceDump(
"InputMethodService#applyVisibilityInInsetsConsumerIfNecessary", mDumper,
null /* icProto */);
- ImeTracker.get().onProgress(mCurStatsToken,
+ ImeTracker.forLogging().onProgress(mCurStatsToken,
ImeTracker.PHASE_IME_APPLY_VISIBILITY_INSETS_CONSUMER);
mPrivOps.applyImeVisibilityAsync(setVisible
? mCurShowInputToken : mCurHideInputToken, setVisible, mCurStatsToken);
diff --git a/core/java/android/inputmethodservice/RemoteInputConnection.java b/core/java/android/inputmethodservice/RemoteInputConnection.java
index f93f9ab..ec26ace 100644
--- a/core/java/android/inputmethodservice/RemoteInputConnection.java
+++ b/core/java/android/inputmethodservice/RemoteInputConnection.java
@@ -476,9 +476,9 @@
@AnyThread
public void requestTextBoundsInfo(
- @NonNull RectF rectF, @NonNull @CallbackExecutor Executor executor,
+ @NonNull RectF bounds, @NonNull @CallbackExecutor Executor executor,
@NonNull Consumer<TextBoundsInfoResult> consumer) {
- mInvoker.requestTextBoundsInfo(rectF, executor, consumer);
+ mInvoker.requestTextBoundsInfo(bounds, executor, consumer);
}
@AnyThread
diff --git a/core/java/android/nfc/BeamShareData.java b/core/java/android/nfc/BeamShareData.java
deleted file mode 100644
index 6a40f98..0000000
--- a/core/java/android/nfc/BeamShareData.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package android.nfc;
-
-import android.net.Uri;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.UserHandle;
-
-/**
- * Class to IPC data to be shared over Android Beam.
- * Allows bundling NdefMessage, Uris and flags in a single
- * IPC call. This is important as we want to reduce the
- * amount of IPC calls at "touch time".
- * @hide
- */
-public final class BeamShareData implements Parcelable {
- public final NdefMessage ndefMessage;
- public final Uri[] uris;
- public final UserHandle userHandle;
- public final int flags;
-
- public BeamShareData(NdefMessage msg, Uri[] uris, UserHandle userHandle, int flags) {
- this.ndefMessage = msg;
- this.uris = uris;
- this.userHandle = userHandle;
- this.flags = flags;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- int urisLength = (uris != null) ? uris.length : 0;
- dest.writeParcelable(ndefMessage, 0);
- dest.writeInt(urisLength);
- if (urisLength > 0) {
- dest.writeTypedArray(uris, 0);
- }
- dest.writeParcelable(userHandle, 0);
- dest.writeInt(this.flags);
- }
-
- public static final @android.annotation.NonNull Parcelable.Creator<BeamShareData> CREATOR =
- new Parcelable.Creator<BeamShareData>() {
- @Override
- public BeamShareData createFromParcel(Parcel source) {
- Uri[] uris = null;
- NdefMessage msg = source.readParcelable(NdefMessage.class.getClassLoader(), android.nfc.NdefMessage.class);
- int numUris = source.readInt();
- if (numUris > 0) {
- uris = new Uri[numUris];
- source.readTypedArray(uris, Uri.CREATOR);
- }
- UserHandle userHandle = source.readParcelable(UserHandle.class.getClassLoader(), android.os.UserHandle.class);
- int flags = source.readInt();
-
- return new BeamShareData(msg, uris, userHandle, flags);
- }
-
- @Override
- public BeamShareData[] newArray(int size) {
- return new BeamShareData[size];
- }
- };
-}
diff --git a/core/java/android/nfc/IAppCallback.aidl b/core/java/android/nfc/IAppCallback.aidl
index 133146d..b06bf06 100644
--- a/core/java/android/nfc/IAppCallback.aidl
+++ b/core/java/android/nfc/IAppCallback.aidl
@@ -16,7 +16,6 @@
package android.nfc;
-import android.nfc.BeamShareData;
import android.nfc.Tag;
/**
@@ -24,7 +23,5 @@
*/
interface IAppCallback
{
- BeamShareData createBeamShareData(byte peerLlcpVersion);
- oneway void onNdefPushComplete(byte peerLlcpVersion);
oneway void onTagDiscovered(in Tag tag);
}
diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl
index de107a2..f6aa4b4 100644
--- a/core/java/android/nfc/INfcAdapter.aidl
+++ b/core/java/android/nfc/INfcAdapter.aidl
@@ -18,7 +18,6 @@
import android.app.PendingIntent;
import android.content.IntentFilter;
-import android.nfc.BeamShareData;
import android.nfc.NdefMessage;
import android.nfc.Tag;
import android.nfc.TechListParcel;
@@ -47,24 +46,18 @@
int getState();
boolean disable(boolean saveState);
boolean enable();
- boolean enableNdefPush();
- boolean disableNdefPush();
- boolean isNdefPushEnabled();
void pausePolling(int timeoutInMs);
void resumePolling();
void setForegroundDispatch(in PendingIntent intent,
in IntentFilter[] filters, in TechListParcel techLists);
void setAppCallback(in IAppCallback callback);
- oneway void invokeBeam();
- oneway void invokeBeamInternal(in BeamShareData shareData);
boolean ignore(int nativeHandle, int debounceMs, ITagRemovedCallback callback);
void dispatch(in Tag tag);
void setReaderMode (IBinder b, IAppCallback callback, int flags, in Bundle extras);
- void setP2pModes(int initatorModes, int targetModes);
void addNfcUnlockHandler(INfcUnlockHandler unlockHandler, in int[] techList);
void removeNfcUnlockHandler(INfcUnlockHandler unlockHandler);
diff --git a/core/java/android/nfc/NfcActivityManager.java b/core/java/android/nfc/NfcActivityManager.java
index 911aaf3..8d75cac 100644
--- a/core/java/android/nfc/NfcActivityManager.java
+++ b/core/java/android/nfc/NfcActivityManager.java
@@ -19,9 +19,6 @@
import android.app.Activity;
import android.app.Application;
import android.compat.annotation.UnsupportedAppUsage;
-import android.content.ContentProvider;
-import android.content.Intent;
-import android.net.Uri;
import android.nfc.NfcAdapter.ReaderCallback;
import android.os.Binder;
import android.os.Bundle;
@@ -110,14 +107,8 @@
class NfcActivityState {
boolean resumed = false;
Activity activity;
- NdefMessage ndefMessage = null; // static NDEF message
- NfcAdapter.CreateNdefMessageCallback ndefMessageCallback = null;
- NfcAdapter.OnNdefPushCompleteCallback onNdefPushCompleteCallback = null;
- NfcAdapter.CreateBeamUrisCallback uriCallback = null;
- Uri[] uris = null;
- int flags = 0;
- int readerModeFlags = 0;
NfcAdapter.ReaderCallback readerCallback = null;
+ int readerModeFlags = 0;
Bundle readerModeExtras = null;
Binder token;
@@ -137,24 +128,16 @@
unregisterApplication(activity.getApplication());
resumed = false;
activity = null;
- ndefMessage = null;
- ndefMessageCallback = null;
- onNdefPushCompleteCallback = null;
- uriCallback = null;
- uris = null;
+ readerCallback = null;
readerModeFlags = 0;
+ readerModeExtras = null;
token = null;
}
@Override
public String toString() {
- StringBuilder s = new StringBuilder("[").append(" ");
- s.append(ndefMessage).append(" ").append(ndefMessageCallback).append(" ");
- s.append(uriCallback).append(" ");
- if (uris != null) {
- for (Uri uri : uris) {
- s.append(onNdefPushCompleteCallback).append(" ").append(uri).append("]");
- }
- }
+ StringBuilder s = new StringBuilder("[");
+ s.append(readerCallback);
+ s.append("]");
return s.toString();
}
}
@@ -245,92 +228,6 @@
}
}
- public void setNdefPushContentUri(Activity activity, Uri[] uris) {
- boolean isResumed;
- synchronized (NfcActivityManager.this) {
- NfcActivityState state = getActivityState(activity);
- state.uris = uris;
- isResumed = state.resumed;
- }
- if (isResumed) {
- // requestNfcServiceCallback() verifies permission also
- requestNfcServiceCallback();
- } else {
- // Crash API calls early in case NFC permission is missing
- verifyNfcPermission();
- }
- }
-
-
- public void setNdefPushContentUriCallback(Activity activity,
- NfcAdapter.CreateBeamUrisCallback callback) {
- boolean isResumed;
- synchronized (NfcActivityManager.this) {
- NfcActivityState state = getActivityState(activity);
- state.uriCallback = callback;
- isResumed = state.resumed;
- }
- if (isResumed) {
- // requestNfcServiceCallback() verifies permission also
- requestNfcServiceCallback();
- } else {
- // Crash API calls early in case NFC permission is missing
- verifyNfcPermission();
- }
- }
-
- public void setNdefPushMessage(Activity activity, NdefMessage message, int flags) {
- boolean isResumed;
- synchronized (NfcActivityManager.this) {
- NfcActivityState state = getActivityState(activity);
- state.ndefMessage = message;
- state.flags = flags;
- isResumed = state.resumed;
- }
- if (isResumed) {
- // requestNfcServiceCallback() verifies permission also
- requestNfcServiceCallback();
- } else {
- // Crash API calls early in case NFC permission is missing
- verifyNfcPermission();
- }
- }
-
- public void setNdefPushMessageCallback(Activity activity,
- NfcAdapter.CreateNdefMessageCallback callback, int flags) {
- boolean isResumed;
- synchronized (NfcActivityManager.this) {
- NfcActivityState state = getActivityState(activity);
- state.ndefMessageCallback = callback;
- state.flags = flags;
- isResumed = state.resumed;
- }
- if (isResumed) {
- // requestNfcServiceCallback() verifies permission also
- requestNfcServiceCallback();
- } else {
- // Crash API calls early in case NFC permission is missing
- verifyNfcPermission();
- }
- }
-
- public void setOnNdefPushCompleteCallback(Activity activity,
- NfcAdapter.OnNdefPushCompleteCallback callback) {
- boolean isResumed;
- synchronized (NfcActivityManager.this) {
- NfcActivityState state = getActivityState(activity);
- state.onNdefPushCompleteCallback = callback;
- isResumed = state.resumed;
- }
- if (isResumed) {
- // requestNfcServiceCallback() verifies permission also
- requestNfcServiceCallback();
- } else {
- // Crash API calls early in case NFC permission is missing
- verifyNfcPermission();
- }
- }
-
/**
* Request or unrequest NFC service callbacks.
* Makes IPC call - do not hold lock.
@@ -351,86 +248,6 @@
}
}
- /** Callback from NFC service, usually on binder thread */
- @Override
- public BeamShareData createBeamShareData(byte peerLlcpVersion) {
- NfcAdapter.CreateNdefMessageCallback ndefCallback;
- NfcAdapter.CreateBeamUrisCallback urisCallback;
- NdefMessage message;
- Activity activity;
- Uri[] uris;
- int flags;
- NfcEvent event = new NfcEvent(mAdapter, peerLlcpVersion);
- synchronized (NfcActivityManager.this) {
- NfcActivityState state = findResumedActivityState();
- if (state == null) return null;
-
- ndefCallback = state.ndefMessageCallback;
- urisCallback = state.uriCallback;
- message = state.ndefMessage;
- uris = state.uris;
- flags = state.flags;
- activity = state.activity;
- }
- final long ident = Binder.clearCallingIdentity();
- try {
- // Make callbacks without lock
- if (ndefCallback != null) {
- message = ndefCallback.createNdefMessage(event);
- }
- if (urisCallback != null) {
- uris = urisCallback.createBeamUris(event);
- if (uris != null) {
- ArrayList<Uri> validUris = new ArrayList<Uri>();
- for (Uri uri : uris) {
- if (uri == null) {
- Log.e(TAG, "Uri not allowed to be null.");
- continue;
- }
- String scheme = uri.getScheme();
- if (scheme == null || (!scheme.equalsIgnoreCase("file") &&
- !scheme.equalsIgnoreCase("content"))) {
- Log.e(TAG, "Uri needs to have " +
- "either scheme file or scheme content");
- continue;
- }
- uri = ContentProvider.maybeAddUserId(uri, activity.getUserId());
- validUris.add(uri);
- }
-
- uris = validUris.toArray(new Uri[validUris.size()]);
- }
- }
- if (uris != null && uris.length > 0) {
- for (Uri uri : uris) {
- // Grant the NFC process permission to read these URIs
- activity.grantUriPermission("com.android.nfc", uri,
- Intent.FLAG_GRANT_READ_URI_PERMISSION);
- }
- }
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- return new BeamShareData(message, uris, activity.getUser(), flags);
- }
-
- /** Callback from NFC service, usually on binder thread */
- @Override
- public void onNdefPushComplete(byte peerLlcpVersion) {
- NfcAdapter.OnNdefPushCompleteCallback callback;
- synchronized (NfcActivityManager.this) {
- NfcActivityState state = findResumedActivityState();
- if (state == null) return;
-
- callback = state.onNdefPushCompleteCallback;
- }
- NfcEvent event = new NfcEvent(mAdapter, peerLlcpVersion);
- // Make callback without lock
- if (callback != null) {
- callback.onNdefPushComplete(event);
- }
- }
-
@Override
public void onTagDiscovered(Tag tag) throws RemoteException {
NfcAdapter.ReaderCallback callback;
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index 0c7f529..c4b3c22 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -338,7 +338,10 @@
*/
public static final String EXTRA_READER_PRESENCE_CHECK_DELAY = "presence";
- /** @hide */
+ /**
+ * @hide
+ * @removed
+ */
@SystemApi
public static final int FLAG_NDEF_PUSH_NO_CONFIRM = 0x1;
@@ -374,7 +377,6 @@
// Guarded by NfcAdapter.class
static boolean sIsInitialized = false;
static boolean sHasNfcFeature;
- static boolean sHasBeamFeature;
// Final after first constructor, except for
// attemptDeadServiceRecovery() when NFC crashes - we accept a best effort
@@ -438,7 +440,7 @@
* A callback to be invoked when the system successfully delivers your {@link NdefMessage}
* to another device.
* @see #setOnNdefPushCompleteCallback
- * @deprecated this feature is deprecated. File sharing can work using other technology like
+ * @removed this feature is removed. File sharing can work using other technology like
* Bluetooth.
*/
@java.lang.Deprecated
@@ -464,7 +466,7 @@
* content currently visible to the user. Alternatively, you can call {@link
* #setNdefPushMessage setNdefPushMessage()} if the {@link NdefMessage} always contains the
* same data.
- * @deprecated this feature is deprecated. File sharing can work using other technology like
+ * @removed this feature is removed. File sharing can work using other technology like
* Bluetooth.
*/
@java.lang.Deprecated
@@ -494,7 +496,7 @@
/**
- * @deprecated this feature is deprecated. File sharing can work using other technology like
+ * @removed this feature is removed. File sharing can work using other technology like
* Bluetooth.
*/
@java.lang.Deprecated
@@ -526,26 +528,6 @@
}
/**
- * Helper to check if this device has FEATURE_NFC_BEAM, but without using
- * a context.
- * Equivalent to
- * context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC_BEAM)
- */
- private static boolean hasBeamFeature() {
- IPackageManager pm = ActivityThread.getPackageManager();
- if (pm == null) {
- Log.e(TAG, "Cannot get package manager, assuming no Android Beam feature");
- return false;
- }
- try {
- return pm.hasSystemFeature(PackageManager.FEATURE_NFC_BEAM, 0);
- } catch (RemoteException e) {
- Log.e(TAG, "Package manager query failed, assuming no Android Beam feature", e);
- return false;
- }
- }
-
- /**
* Helper to check if this device has FEATURE_NFC, but without using
* a context.
* Equivalent to
@@ -624,7 +606,6 @@
public static synchronized NfcAdapter getNfcAdapter(Context context) {
if (!sIsInitialized) {
sHasNfcFeature = hasNfcFeature();
- sHasBeamFeature = hasBeamFeature();
boolean hasHceFeature = hasNfcHceFeature();
/* is this device meant to have NFC */
if (!sHasNfcFeature && !hasHceFeature) {
@@ -1117,7 +1098,7 @@
* @param uris an array of Uri(s) to push over Android Beam
* @param activity activity for which the Uri(s) will be pushed
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
- * @deprecated this feature is deprecated. File sharing can work using other technology like
+ * @removed this feature is removed. File sharing can work using other technology like
* Bluetooth.
*/
@java.lang.Deprecated
@@ -1126,26 +1107,7 @@
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
- if (!sHasBeamFeature) {
- return;
- }
}
- if (activity == null) {
- throw new NullPointerException("activity cannot be null");
- }
- if (uris != null) {
- for (Uri uri : uris) {
- if (uri == null) throw new NullPointerException("Uri not " +
- "allowed to be null");
- String scheme = uri.getScheme();
- if (scheme == null || (!scheme.equalsIgnoreCase("file") &&
- !scheme.equalsIgnoreCase("content"))) {
- throw new IllegalArgumentException("URI needs to have " +
- "either scheme file or scheme content");
- }
- }
- }
- mNfcActivityManager.setNdefPushContentUri(activity, uris);
}
/**
@@ -1205,7 +1167,7 @@
* @param callback callback, or null to disable
* @param activity activity for which the Uri(s) will be pushed
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
- * @deprecated this feature is deprecated. File sharing can work using other technology like
+ * @removed this feature is removed. File sharing can work using other technology like
* Bluetooth.
*/
@java.lang.Deprecated
@@ -1214,14 +1176,7 @@
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
- if (!sHasBeamFeature) {
- return;
- }
}
- if (activity == null) {
- throw new NullPointerException("activity cannot be null");
- }
- mNfcActivityManager.setNdefPushContentUriCallback(activity, callback);
}
/**
@@ -1295,7 +1250,7 @@
* to only register one at a time, and to do so in that activity's
* {@link Activity#onCreate}
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
- * @deprecated this feature is deprecated. File sharing can work using other technology like
+ * @removed this feature is removed. File sharing can work using other technology like
* Bluetooth.
*/
@java.lang.Deprecated
@@ -1305,36 +1260,12 @@
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
- if (!sHasBeamFeature) {
- return;
- }
- }
- int targetSdkVersion = getSdkVersion();
- try {
- if (activity == null) {
- throw new NullPointerException("activity cannot be null");
- }
- mNfcActivityManager.setNdefPushMessage(activity, message, 0);
- for (Activity a : activities) {
- if (a == null) {
- throw new NullPointerException("activities cannot contain null");
- }
- mNfcActivityManager.setNdefPushMessage(a, message, 0);
- }
- } catch (IllegalStateException e) {
- if (targetSdkVersion < android.os.Build.VERSION_CODES.JELLY_BEAN) {
- // Less strict on old applications - just log the error
- Log.e(TAG, "Cannot call API with Activity that has already " +
- "been destroyed", e);
- } else {
- // Prevent new applications from making this mistake, re-throw
- throw(e);
- }
}
}
/**
* @hide
+ * @removed
*/
@SystemApi
public void setNdefPushMessage(NdefMessage message, Activity activity, int flags) {
@@ -1343,10 +1274,6 @@
throw new UnsupportedOperationException();
}
}
- if (activity == null) {
- throw new NullPointerException("activity cannot be null");
- }
- mNfcActivityManager.setNdefPushMessage(activity, message, flags);
}
/**
@@ -1414,7 +1341,7 @@
* to only register one at a time, and to do so in that activity's
* {@link Activity#onCreate}
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
- * @deprecated this feature is deprecated. File sharing can work using other technology like
+ * @removed this feature is removed. File sharing can work using other technology like
* Bluetooth.
*/
@java.lang.Deprecated
@@ -1424,44 +1351,7 @@
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
- if (!sHasBeamFeature) {
- return;
- }
}
- int targetSdkVersion = getSdkVersion();
- try {
- if (activity == null) {
- throw new NullPointerException("activity cannot be null");
- }
- mNfcActivityManager.setNdefPushMessageCallback(activity, callback, 0);
- for (Activity a : activities) {
- if (a == null) {
- throw new NullPointerException("activities cannot contain null");
- }
- mNfcActivityManager.setNdefPushMessageCallback(a, callback, 0);
- }
- } catch (IllegalStateException e) {
- if (targetSdkVersion < android.os.Build.VERSION_CODES.JELLY_BEAN) {
- // Less strict on old applications - just log the error
- Log.e(TAG, "Cannot call API with Activity that has already " +
- "been destroyed", e);
- } else {
- // Prevent new applications from making this mistake, re-throw
- throw(e);
- }
- }
- }
-
- /**
- * @hide
- */
- @UnsupportedAppUsage
- public void setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity,
- int flags) {
- if (activity == null) {
- throw new NullPointerException("activity cannot be null");
- }
- mNfcActivityManager.setNdefPushMessageCallback(activity, callback, flags);
}
/**
@@ -1501,7 +1391,7 @@
* to only register one at a time, and to do so in that activity's
* {@link Activity#onCreate}
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
- * @deprecated this feature is deprecated. File sharing can work using other technology like
+ * @removed this feature is removed. File sharing can work using other technology like
* Bluetooth.
*/
@java.lang.Deprecated
@@ -1511,31 +1401,6 @@
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
- if (!sHasBeamFeature) {
- return;
- }
- }
- int targetSdkVersion = getSdkVersion();
- try {
- if (activity == null) {
- throw new NullPointerException("activity cannot be null");
- }
- mNfcActivityManager.setOnNdefPushCompleteCallback(activity, callback);
- for (Activity a : activities) {
- if (a == null) {
- throw new NullPointerException("activities cannot contain null");
- }
- mNfcActivityManager.setOnNdefPushCompleteCallback(a, callback);
- }
- } catch (IllegalStateException e) {
- if (targetSdkVersion < android.os.Build.VERSION_CODES.JELLY_BEAN) {
- // Less strict on old applications - just log the error
- Log.e(TAG, "Cannot call API with Activity that has already " +
- "been destroyed", e);
- } else {
- // Prevent new applications from making this mistake, re-throw
- throw(e);
- }
}
}
@@ -1718,7 +1583,7 @@
* @param activity the current foreground Activity that has registered data to share
* @return whether the Beam animation was successfully invoked
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
- * @deprecated this feature is deprecated. File sharing can work using other technology like
+ * @removed this feature is removed. File sharing can work using other technology like
* Bluetooth.
*/
@java.lang.Deprecated
@@ -1727,37 +1592,8 @@
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
- if (!sHasBeamFeature) {
- return false;
- }
}
- if (activity == null) {
- throw new NullPointerException("activity may not be null.");
- }
- enforceResumed(activity);
- try {
- sService.invokeBeam();
- return true;
- } catch (RemoteException e) {
- Log.e(TAG, "invokeBeam: NFC process has died.");
- attemptDeadServiceRecovery(e);
- return false;
- }
- }
-
- /**
- * @hide
- */
- public boolean invokeBeam(BeamShareData shareData) {
- try {
- Log.e(TAG, "invokeBeamInternal()");
- sService.invokeBeamInternal(shareData);
- return true;
- } catch (RemoteException e) {
- Log.e(TAG, "invokeBeam: NFC process has died.");
- attemptDeadServiceRecovery(e);
- return false;
- }
+ return false;
}
/**
@@ -1783,9 +1619,9 @@
*
* @param activity foreground activity
* @param message a NDEF Message to push over NFC
- * @throws IllegalStateException if the activity is not currently in the foreground
- * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
- * @deprecated use {@link #setNdefPushMessage} instead
+ * @throws UnsupportedOperationException if FEATURE_NFC is unavailable
+ * @removed this feature is removed. File sharing can work using other technology like
+ * Bluetooth.
*/
@Deprecated
public void enableForegroundNdefPush(Activity activity, NdefMessage message) {
@@ -1793,15 +1629,7 @@
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
- if (!sHasBeamFeature) {
- return;
- }
}
- if (activity == null || message == null) {
- throw new NullPointerException();
- }
- enforceResumed(activity);
- mNfcActivityManager.setNdefPushMessage(activity, message, 0);
}
/**
@@ -1820,9 +1648,9 @@
* <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
*
* @param activity the Foreground activity
- * @throws IllegalStateException if the Activity has already been paused
- * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
- * @deprecated use {@link #setNdefPushMessage} instead
+ * @throws UnsupportedOperationException if FEATURE_NFC is unavailable
+ * @removed this feature is removed. File sharing can work using other technology like
+ * Bluetooth.
*/
@Deprecated
public void disableForegroundNdefPush(Activity activity) {
@@ -1830,17 +1658,7 @@
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
- if (!sHasBeamFeature) {
- return;
- }
}
- if (activity == null) {
- throw new NullPointerException();
- }
- enforceResumed(activity);
- mNfcActivityManager.setNdefPushMessage(activity, null, 0);
- mNfcActivityManager.setNdefPushMessageCallback(activity, null, 0);
- mNfcActivityManager.setOnNdefPushCompleteCallback(activity, null);
}
/**
@@ -1965,40 +1783,24 @@
* Enable NDEF Push feature.
* <p>This API is for the Settings application.
* @hide
+ * @removed
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
public boolean enableNdefPush() {
- if (!sHasNfcFeature) {
- throw new UnsupportedOperationException();
- }
- try {
- return sService.enableNdefPush();
- } catch (RemoteException e) {
- attemptDeadServiceRecovery(e);
- return false;
- }
+ return false;
}
/**
* Disable NDEF Push feature.
* <p>This API is for the Settings application.
* @hide
+ * @removed
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
public boolean disableNdefPush() {
- synchronized (NfcAdapter.class) {
- if (!sHasNfcFeature) {
- throw new UnsupportedOperationException();
- }
- }
- try {
- return sService.disableNdefPush();
- } catch (RemoteException e) {
- attemptDeadServiceRecovery(e);
- return false;
- }
+ return false;
}
/**
@@ -2024,26 +1826,17 @@
* @see android.provider.Settings#ACTION_NFCSHARING_SETTINGS
* @return true if NDEF Push feature is enabled
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
- * @deprecated this feature is deprecated. File sharing can work using other technology like
+ * @removed this feature is removed. File sharing can work using other technology like
* Bluetooth.
*/
@java.lang.Deprecated
-
public boolean isNdefPushEnabled() {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
- if (!sHasBeamFeature) {
- return false;
- }
}
- try {
- return sService.isNdefPushEnabled();
- } catch (RemoteException e) {
- attemptDeadServiceRecovery(e);
- return false;
- }
+ return false;
}
/**
@@ -2134,17 +1927,6 @@
}
/**
- * @hide
- */
- public void setP2pModes(int initiatorModes, int targetModes) {
- try {
- sService.setP2pModes(initiatorModes, targetModes);
- } catch (RemoteException e) {
- attemptDeadServiceRecovery(e);
- }
- }
-
- /**
* Registers a new NFC unlock handler with the NFC service.
*
* <p />NFC unlock handlers are intended to unlock the keyguard in the presence of a trusted
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 34aa7ef..547d406 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -1142,6 +1142,16 @@
@BatteryConsumer.ProcessState int processState);
+
+ /**
+ * Returns the battery consumption (in microcoulombs) of UID's camera usage, derived from
+ * on-device power measurement data.
+ * Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable.
+ *
+ * {@hide}
+ */
+ public abstract long getCameraEnergyConsumptionUC();
+
/**
* Returns the battery consumption (in microcoulombs) used by this uid for each
* {@link android.hardware.power.stats.EnergyConsumer.ordinal} of (custom) energy consumer
@@ -2921,6 +2931,15 @@
public abstract long getWifiEnergyConsumptionUC();
/**
+ * Returns the battery consumption (in microcoulombs) of camera, derived from on
+ * device power measurement data.
+ * Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable.
+ *
+ * {@hide}
+ */
+ public abstract long getCameraEnergyConsumptionUC();
+
+ /**
* Returns the battery consumption (in microcoulombs) that each
* {@link android.hardware.power.stats.EnergyConsumer.ordinal} of (custom) energy consumer
* type {@link android.hardware.power.stats.EnergyConsumerType#OTHER}) consumed.
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index def0cbd..00676f3 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -358,16 +358,16 @@
* Return the Linux UID assigned to the process that sent the transaction
* currently being processed.
*
- * Logs WTF if the current thread is not currently
+ * Slog.wtf if the current thread is not currently
* executing an incoming transaction and the calling identity has not been
* explicitly set with {@link #clearCallingIdentity()}
*
* @hide
*/
- public static final int getCallingUidOrWtf() {
+ public static final int getCallingUidOrWtf(String message) {
if (!isDirectlyHandlingTransaction() && !hasExplicitIdentity()) {
- Log.wtfStack(TAG,
- "Thread is not in a binder transaction, "
+ Slog.wtf(TAG,
+ message + ": Thread is not in a binder transaction, "
+ "and the calling identity has not been "
+ "explicitly set with clearCallingIdentity");
}
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 249f486..32773a0 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -754,12 +754,9 @@
* PackageManager.setComponentEnabledSetting} will now throw an
* IllegalArgumentException if the given component class name does not
* exist in the application's manifest.
- * <li> {@link android.nfc.NfcAdapter#setNdefPushMessage
- * NfcAdapter.setNdefPushMessage},
- * {@link android.nfc.NfcAdapter#setNdefPushMessageCallback
- * NfcAdapter.setNdefPushMessageCallback} and
- * {@link android.nfc.NfcAdapter#setOnNdefPushCompleteCallback
- * NfcAdapter.setOnNdefPushCompleteCallback} will throw
+ * <li> {@code NfcAdapter.setNdefPushMessage},
+ * {@code NfcAdapter.setNdefPushMessageCallback} and
+ * {@code NfcAdapter.setOnNdefPushCompleteCallback} will throw
* IllegalStateException if called after the Activity has been destroyed.
* <li> Accessibility services must require the new
* {@link android.Manifest.permission#BIND_ACCESSIBILITY_SERVICE} permission or
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index 3b4e8cd..d1d3315 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -142,4 +142,8 @@
long getUserStartRealtime();
long getUserUnlockRealtime();
boolean setUserEphemeral(int userId, boolean enableEphemeral);
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS})")
+ void setBootUser(int userId);
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS})")
+ int getBootUser();
}
diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java
index cdde18a..adc73c8 100644
--- a/core/java/android/os/Trace.java
+++ b/core/java/android/os/Trace.java
@@ -395,19 +395,6 @@
}
/**
- * @deprecated use asyncTraceForTrackEnd without methodName argument
- *
- * @hide
- */
- @Deprecated
- public static void asyncTraceForTrackEnd(long traceTag,
- @NonNull String trackName, @NonNull String methodName, int cookie) {
- if (isTagEnabled(traceTag)) {
- nativeAsyncTraceForTrackEnd(traceTag, trackName, cookie);
- }
- }
-
- /**
* Writes a trace message to indicate that a given section of code was invoked.
*
* @param traceTag The trace tag.
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 0e4c2b2..9db1233 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1472,6 +1472,21 @@
public static final String DISALLOW_BIOMETRIC = "disallow_biometric";
/**
+ * Specifies whether the user is allowed to modify default apps in settings.
+ *
+ * <p>This restriction can be set by device or profile owner.
+ *
+ * <p>The default value is <code>false</code>.
+ *
+ * <p>Key for user restrictions.
+ * <p>Type: Boolean
+ * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+ * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
+ * @see #getUserRestrictions()
+ */
+ public static final String DISALLOW_CONFIG_DEFAULT_APPS = "disallow_config_default_apps";
+
+ /**
* Application restriction key that is used to indicate the pending arrival
* of real restrictions for the app.
*
@@ -5656,6 +5671,40 @@
}
}
+ /**
+ * Sets the user who should be in the foreground when boot completes. This should be called
+ * during boot, and the provided user must be a full user (i.e. not a profile).
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
+ Manifest.permission.CREATE_USERS})
+ public void setBootUser(@NonNull UserHandle bootUser) {
+ try {
+ mService.setBootUser(bootUser.getIdentifier());
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns the user who should be in the foreground when boot completes.
+ *
+ * @hide
+ */
+ @TestApi
+ @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
+ Manifest.permission.CREATE_USERS})
+ @SuppressWarnings("[AndroidFrameworkContextUserId]")
+ public @NonNull UserHandle getBootUser() {
+ try {
+ return UserHandle.of(mService.getBootUser());
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
/* Cache key for anything that assumes that userIds cannot be re-used without rebooting. */
private static final String CACHE_KEY_STATIC_USER_PROPERTIES = "cache_key.static_user_props";
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 190b738..9a848af 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -22,6 +22,8 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.PermissionMethod;
+import android.annotation.PermissionName;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
@@ -48,7 +50,6 @@
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
-import android.content.pm.PermissionName;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -602,6 +603,8 @@
* Output: When a package data uri is passed as input, the activity result is set to
* {@link android.app.Activity#RESULT_OK} if the permission was granted to the app. Otherwise,
* the result is set to {@link android.app.Activity#RESULT_CANCELED}.
+ *
+ * @hide
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_MANAGE_APP_LONG_RUNNING_JOBS =
@@ -1691,7 +1694,6 @@
* Input: Nothing.
* <p>
* Output: Nothing
- * @see android.nfc.NfcAdapter#isNdefPushEnabled()
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_NFCSHARING_SETTINGS =
@@ -9400,6 +9402,14 @@
public static final int DOCK_SETUP_PROMPTED = 3;
/**
+ * Indicates that the user has started dock setup but never finished it.
+ * One of the possible states for {@link #DOCK_SETUP_STATE}.
+ *
+ * @hide
+ */
+ public static final int DOCK_SETUP_INCOMPLETE = 4;
+
+ /**
* Indicates that the user has completed dock setup.
* One of the possible states for {@link #DOCK_SETUP_STATE}.
*
@@ -9407,6 +9417,14 @@
*/
public static final int DOCK_SETUP_COMPLETED = 10;
+ /**
+ * Indicates that dock setup timed out before the user could complete it.
+ * One of the possible states for {@link #DOCK_SETUP_STATE}.
+ *
+ * @hide
+ */
+ public static final int DOCK_SETUP_TIMED_OUT = 11;
+
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef({
@@ -9414,7 +9432,9 @@
DOCK_SETUP_STARTED,
DOCK_SETUP_PAUSED,
DOCK_SETUP_PROMPTED,
- DOCK_SETUP_COMPLETED
+ DOCK_SETUP_INCOMPLETE,
+ DOCK_SETUP_COMPLETED,
+ DOCK_SETUP_TIMED_OUT
})
public @interface DockSetupState {
}
@@ -9986,11 +10006,10 @@
"fingerprint_side_fps_auth_downtime";
/**
- * Whether or not a SFPS device is required to be interactive for auth to unlock the device.
+ * Whether or not a SFPS device is enabling the performant auth setting.
* @hide
*/
- public static final String SFPS_REQUIRE_SCREEN_ON_TO_AUTH_ENABLED =
- "sfps_require_screen_on_to_auth_enabled";
+ public static final String SFPS_PERFORMANT_AUTH_ENABLED = "sfps_performant_auth_enabled";
/**
* Whether or not debugging is enabled.
@@ -18503,6 +18522,8 @@
* @see #checkCallingPermission
* @hide
*/
+ @PermissionMethod(orSelf = true)
+ @PackageManager.PermissionResult
public static int checkCallingOrSelfPermission(@NonNull @PermissionName String permission) {
return ActivityThread.currentApplication()
.getApplicationContext().checkCallingOrSelfPermission(permission);
diff --git a/core/java/android/security/net/config/SystemCertificateSource.java b/core/java/android/security/net/config/SystemCertificateSource.java
index 4892312..13f7e5d 100644
--- a/core/java/android/security/net/config/SystemCertificateSource.java
+++ b/core/java/android/security/net/config/SystemCertificateSource.java
@@ -41,7 +41,7 @@
private static File getDirectory() {
// TODO(miguelaranda): figure out correct code path.
File updatable_dir = new File("/apex/com.android.conscrypt/cacerts");
- if (updatable_dir.exists()) {
+ if (updatable_dir.exists() && !(updatable_dir.list().length == 0)) {
return updatable_dir;
}
return new File(System.getenv("ANDROID_ROOT") + "/etc/security/cacerts");
diff --git a/core/java/android/security/rkp/IRegistration.aidl b/core/java/android/security/rkp/IRegistration.aidl
index 6522a45..8ec13b9 100644
--- a/core/java/android/security/rkp/IRegistration.aidl
+++ b/core/java/android/security/rkp/IRegistration.aidl
@@ -17,6 +17,7 @@
package android.security.rkp;
import android.security.rkp.IGetKeyCallback;
+import android.security.rkp.IStoreUpgradedKeyCallback;
/**
* This interface is associated with the registration of an
@@ -70,16 +71,18 @@
* mechanism, see the documentation for IKeyMintDevice.upgradeKey.
*
* Once a key has been upgraded, the IRegistration where the key is stored
- * needs to be told about the new blob. After calling storeUpgradedKey,
+ * needs to be told about the new blob. After calling storeUpgradedKeyAsync,
* getKey will return the new key blob instead of the old one.
*
* Note that this function does NOT extend the lifetime of key blobs. The
* certificate for the key is unchanged, and the key will still expire at
- * the same time it would have if storeUpgradedKey had never been called.
+ * the same time it would have if storeUpgradedKeyAsync had never been called.
*
* @param oldKeyBlob The old key blob to be replaced by {@code newKeyBlob}.
- *
* @param newKeyblob The new blob to replace {@code oldKeyBlob}.
+ * @param callback Receives the result of the call. A callback must only
+ * be used with one {@code storeUpgradedKeyAsync} call at a time.
*/
- void storeUpgradedKey(in byte[] oldKeyBlob, in byte[] newKeyBlob);
+ void storeUpgradedKeyAsync(
+ in byte[] oldKeyBlob, in byte[] newKeyBlob, IStoreUpgradedKeyCallback callback);
}
diff --git a/core/java/android/security/rkp/IStoreUpgradedKeyCallback.aidl b/core/java/android/security/rkp/IStoreUpgradedKeyCallback.aidl
new file mode 100644
index 0000000..7f72fa0
--- /dev/null
+++ b/core/java/android/security/rkp/IStoreUpgradedKeyCallback.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.rkp;
+
+/**
+ * Callback interface for storing an upgraded remotely provisioned key blob.
+ * {@link IRegistration}.
+ *
+ * @hide
+ */
+oneway interface IStoreUpgradedKeyCallback {
+ /**
+ * Called in response to {@link IRegistration.storeUpgradedKeyAsync}, indicating
+ * a remotely-provisioned key is available.
+ */
+ void onSuccess();
+
+ /**
+ * Called when an error has occurred while trying to store an upgraded
+ * remotely provisioned key.
+ *
+ * @param error A description of what failed, suitable for logging.
+ */
+ void onError(String error);
+}
diff --git a/core/java/android/service/appprediction/AppPredictionService.java b/core/java/android/service/appprediction/AppPredictionService.java
index 4f37cd9..a2ffa5d 100644
--- a/core/java/android/service/appprediction/AppPredictionService.java
+++ b/core/java/android/service/appprediction/AppPredictionService.java
@@ -328,7 +328,7 @@
Slog.e(TAG, "Callback is null, likely the binder has died.");
return false;
}
- return mCallback.equals(callback);
+ return mCallback.asBinder().equals(callback.asBinder());
}
public void destroy() {
diff --git a/core/java/android/service/autofill/FillEventHistory.java b/core/java/android/service/autofill/FillEventHistory.java
index 0fb9f57..b0e847c 100644
--- a/core/java/android/service/autofill/FillEventHistory.java
+++ b/core/java/android/service/autofill/FillEventHistory.java
@@ -166,7 +166,7 @@
}
/**
- * Description of an event that occured after the latest call to
+ * Description of an event that occurred after the latest call to
* {@link FillCallback#onSuccess(FillResponse)}.
*/
public static final class Event {
diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java
index 78f91ed..385b0aa 100644
--- a/core/java/android/service/autofill/FillResponse.java
+++ b/core/java/android/service/autofill/FillResponse.java
@@ -20,9 +20,11 @@
import static android.service.autofill.FillRequest.INVALID_REQUEST_ID;
import static android.view.autofill.Helper.sDebug;
+import android.annotation.DrawableRes;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.StringRes;
import android.annotation.SuppressLint;
import android.annotation.TestApi;
import android.app.Activity;
@@ -107,6 +109,10 @@
private final @Nullable UserData mUserData;
private final @Nullable int[] mCancelIds;
private final boolean mSupportsInlineSuggestions;
+ private final @DrawableRes int mIconResourceId;
+ private final @StringRes int mServiceDisplayNameResourceId;
+ private final boolean mShowFillDialogIcon;
+ private final boolean mShowSaveDialogIcon;
private FillResponse(@NonNull Builder builder) {
mDatasets = (builder.mDatasets != null) ? new ParceledListSlice<>(builder.mDatasets) : null;
@@ -130,6 +136,10 @@
mUserData = builder.mUserData;
mCancelIds = builder.mCancelIds;
mSupportsInlineSuggestions = builder.mSupportsInlineSuggestions;
+ mIconResourceId = builder.mIconResourceId;
+ mServiceDisplayNameResourceId = builder.mServiceDisplayNameResourceId;
+ mShowFillDialogIcon = builder.mShowFillDialogIcon;
+ mShowSaveDialogIcon = builder.mShowSaveDialogIcon;
}
/** @hide */
@@ -218,6 +228,26 @@
}
/** @hide */
+ public @DrawableRes int getIconResourceId() {
+ return mIconResourceId;
+ }
+
+ /** @hide */
+ public @StringRes int getServiceDisplayNameResourceId() {
+ return mServiceDisplayNameResourceId;
+ }
+
+ /** @hide */
+ public boolean getShowFillDialogIcon() {
+ return mShowFillDialogIcon;
+ }
+
+ /** @hide */
+ public boolean getShowSaveDialogIcon() {
+ return mShowSaveDialogIcon;
+ }
+
+ /** @hide */
@TestApi
public int getFlags() {
return mFlags;
@@ -278,6 +308,10 @@
private UserData mUserData;
private int[] mCancelIds;
private boolean mSupportsInlineSuggestions;
+ private int mIconResourceId;
+ private int mServiceDisplayNameResourceId;
+ private boolean mShowFillDialogIcon = true;
+ private boolean mShowSaveDialogIcon = true;
/**
* Triggers a custom UI before autofilling the screen with any data set in this
@@ -729,6 +763,70 @@
}
/**
+ * Overwrites Save/Fill dialog header icon with a specific one specified by resource id.
+ * The image is pulled from the package, so id should be defined in the manifest.
+ *
+ * @param id {@link android.graphics.drawable.Drawable} resource id of the icon to be used.
+ * A value of 0 indicates to use the default header icon.
+ *
+ * @return this builder
+ */
+ @NonNull
+ public Builder setIconResourceId(@DrawableRes int id) {
+ throwIfDestroyed();
+
+ mIconResourceId = id;
+ return this;
+ }
+
+ /**
+ * Overrides the service name in the Save Dialog header with a specific string defined
+ * in the service provider's manifest.xml
+ *
+ * @param id Resoure Id of the custom string defined in the provider's manifest. If set
+ * to 0, the default name will be used.
+ *
+ * @return this builder
+ */
+ @NonNull
+ public Builder setServiceDisplayNameResourceId(@StringRes int id) {
+ throwIfDestroyed();
+
+ mServiceDisplayNameResourceId = id;
+ return this;
+ }
+
+ /**
+ * Whether or not to show the Autofill provider icon inside of the Fill Dialog
+ *
+ * @param show True to show, false to hide. Defaults to true.
+ *
+ * @return this builder
+ */
+ @NonNull
+ public Builder setShowFillDialogIcon(boolean show) {
+ throwIfDestroyed();
+
+ mShowFillDialogIcon = show;
+ return this;
+ }
+
+ /**
+ * Whether or not to show the Autofill provider icon inside of the Save Dialog
+ *
+ * @param show True to show, false to hide. Defaults to true.
+ *
+ * @return this builder
+ */
+ @NonNull
+ public Builder setShowSaveDialogIcon(boolean show) {
+ throwIfDestroyed();
+
+ mShowSaveDialogIcon = show;
+ return this;
+ }
+
+ /**
* Sets a header to be shown as the first element in the list of datasets.
*
* <p>When this method is called, you must also {@link #addDataset(Dataset) add a dataset},
@@ -1024,6 +1122,10 @@
parcel.writeParcelableArray(mIgnoredIds, flags);
parcel.writeLong(mDisableDuration);
parcel.writeParcelableArray(mFieldClassificationIds, flags);
+ parcel.writeInt(mIconResourceId);
+ parcel.writeInt(mServiceDisplayNameResourceId);
+ parcel.writeBoolean(mShowFillDialogIcon);
+ parcel.writeBoolean(mShowSaveDialogIcon);
parcel.writeInt(mFlags);
parcel.writeIntArray(mCancelIds);
parcel.writeInt(mRequestId);
@@ -1089,6 +1191,11 @@
if (fieldClassifactionIds != null) {
builder.setFieldClassificationIds(fieldClassifactionIds);
}
+
+ builder.setIconResourceId(parcel.readInt());
+ builder.setServiceDisplayNameResourceId(parcel.readInt());
+ builder.setShowFillDialogIcon(parcel.readBoolean());
+ builder.setShowSaveDialogIcon(parcel.readBoolean());
builder.setFlags(parcel.readInt());
final int[] cancelIds = parcel.createIntArray();
builder.setPresentationCancelIds(cancelIds);
diff --git a/core/java/android/service/credentials/CredentialProviderService.java b/core/java/android/service/credentials/CredentialProviderService.java
index 0a3d95d..ee386c3 100644
--- a/core/java/android/service/credentials/CredentialProviderService.java
+++ b/core/java/android/service/credentials/CredentialProviderService.java
@@ -125,6 +125,33 @@
public static final String EXTRA_CREATE_CREDENTIAL_EXCEPTION =
"android.service.credentials.extra.CREATE_CREDENTIAL_EXCEPTION";
+ /**
+ * Intent extra: The {@link BeginGetCredentialRequest} attached with
+ * the {@code pendingIntent} that is invoked when the user selects an
+ * authentication entry (intending to unlock the provider app) on the UI.
+ *
+ * <p>When a provider app receives a {@link BeginGetCredentialRequest} through the
+ * {@link CredentialProviderService#onBeginGetCredential} call, it can construct the
+ * {@link BeginGetCredentialResponse} with either an authentication {@link Action} (if the app
+ * is locked), or a {@link CredentialsResponseContent} (if the app is unlocked). In the former
+ * case, i.e. the app is locked, user will be shown the authentication action. When selected,
+ * the underlying {@link PendingIntent} will be invoked which will lead the user to provider's
+ * unlock activity. This pending intent will also contain the original
+ * {@link BeginGetCredentialRequest} to be retrieved and processed after the unlock
+ * flow is complete.
+ *
+ * <p>After the app is unlocked, the {@link BeginGetCredentialResponse} must be constructed
+ * using a {@link CredentialsResponseContent}, which must be set on an {@link Intent} as an
+ * intent extra against CredentialProviderService#EXTRA_CREDENTIALS_RESPONSE_CONTENT}.
+ * This intent should then be set as a result through {@link android.app.Activity#setResult}
+ * before finishing the activity.
+ *
+ * <p>
+ * Type: {@link BeginGetCredentialRequest}
+ */
+ public static final String EXTRA_BEGIN_GET_CREDENTIAL_REQUEST =
+ "android.service.credentials.extra.BEGIN_GET_CREDENTIAL_REQUEST";
+
private static final String TAG = "CredProviderService";
public static final String CAPABILITY_META_DATA_KEY = "android.credentials.capabilities";
diff --git a/core/java/android/service/smartspace/SmartspaceService.java b/core/java/android/service/smartspace/SmartspaceService.java
index 3a148df..b13a069 100644
--- a/core/java/android/service/smartspace/SmartspaceService.java
+++ b/core/java/android/service/smartspace/SmartspaceService.java
@@ -302,7 +302,7 @@
Slog.e(TAG, "Callback is null, likely the binder has died.");
return false;
}
- return mCallback.equals(callback);
+ return mCallback.asBinder().equals(callback.asBinder());
}
@Override
diff --git a/core/java/android/service/voice/AbstractDetector.java b/core/java/android/service/voice/AbstractDetector.java
index db0ede5..a70f783 100644
--- a/core/java/android/service/voice/AbstractDetector.java
+++ b/core/java/android/service/voice/AbstractDetector.java
@@ -84,7 +84,7 @@
@Nullable SharedMemory sharedMemory);
/**
- * Detect hotword from an externally supplied stream of data.
+ * Detect from an externally supplied stream of data.
*
* @return {@code true} if the request to start recognition succeeded
*/
@@ -114,7 +114,25 @@
return true;
}
- /** {@inheritDoc} */
+ /**
+ * Set configuration and pass read-only data to trusted detection service.
+ *
+ * @param options Application configuration data to provide to the
+ * {@link VisualQueryDetectionService} and {@link HotwordDetectionService}.
+ * PersistableBundle does not allow any remotable objects or other contents that can be
+ * used to communicate with other processes.
+ * @param sharedMemory The unrestricted data blob to provide to the
+ * {@link VisualQueryDetectionService} and {@link HotwordDetectionService}. Use this to
+ * provide the hotword models data or other such data to the trusted process.
+ * @throws IllegalDetectorStateException Thrown when a caller has a target SDK of
+ * Android Tiramisu or above and attempts to start a recognition when the detector is
+ * not able based on the state. Because the caller receives updates via an asynchronous
+ * callback and the state of the detector can change without caller's knowledge, a
+ * checked exception is thrown.
+ * @throws IllegalStateException if this {@link HotwordDetector} wasn't specified to use a
+ * {@link HotwordDetectionService} or {@link VisualQueryDetectionService} when it was
+ * created.
+ */
@Override
public void updateState(@Nullable PersistableBundle options,
@Nullable SharedMemory sharedMemory) throws IllegalDetectorStateException {
diff --git a/core/java/android/service/voice/HotwordDetectionService.java b/core/java/android/service/voice/HotwordDetectionService.java
index f3d4809..0384454 100644
--- a/core/java/android/service/voice/HotwordDetectionService.java
+++ b/core/java/android/service/voice/HotwordDetectionService.java
@@ -194,6 +194,12 @@
}
@Override
+ public void detectWithVisualSignals(
+ IDetectorSessionVisualQueryDetectionCallback callback) {
+ throw new UnsupportedOperationException("Not supported by HotwordDetectionService");
+ }
+
+ @Override
public void updateAudioFlinger(IBinder audioFlinger) {
AudioSystem.setAudioFlingerBinder(audioFlinger);
}
@@ -382,7 +388,7 @@
*/
@SystemApi
public static final class Callback {
- // TODO: need to make sure we don't store remote references, but not a high priority.
+ // TODO: consider making the constructor a test api for testing purpose
private final IDspHotwordDetectionCallback mRemoteCallback;
private Callback(IDspHotwordDetectionCallback remoteCallback) {
diff --git a/core/java/android/service/voice/HotwordDetector.java b/core/java/android/service/voice/HotwordDetector.java
index 669c22b..562277e 100644
--- a/core/java/android/service/voice/HotwordDetector.java
+++ b/core/java/android/service/voice/HotwordDetector.java
@@ -35,7 +35,8 @@
import java.io.PrintWriter;
/**
- * Basic functionality for sandboxed detectors.
+ * Basic functionality for sandboxed detectors. This interface will be used by detectors that
+ * manages their service lifecycle.
*
* @hide
*/
@@ -81,9 +82,20 @@
int DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE = 2;
/**
+ * Indicates that it is a visual query detector.
+ *
+ * @hide
+ */
+ int DETECTOR_TYPE_VISUAL_QUERY_DETECTOR = 3;
+
+ /**
* Starts sandboxed detection recognition.
* <p>
- * On calling this, the system streams audio from the device microphone to this application's
+ * If a {@link VisualQueryDetector} calls this method, {@link VisualQueryDetectionService
+ * #onStartDetection(VisualQueryDetectionService.Callback)} will be called to start detection.
+ * <p>
+ * Otherwise if a {@link AlwaysOnHotwordDetector} or {@link SoftwareHotwordDetector} calls this,
+ * the system streams audio from the device microphone to this application's
* {@link HotwordDetectionService}. Audio is streamed until {@link #stopRecognition()} is
* called.
* <p>
@@ -192,6 +204,8 @@
return "trusted_hotword_dsp";
case DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE:
return "trusted_hotword_software";
+ case DETECTOR_TYPE_VISUAL_QUERY_DETECTOR:
+ return "visual_query_detector";
default:
return Integer.toString(detectorType);
}
@@ -244,18 +258,21 @@
void onRejected(@NonNull HotwordRejectedResult result);
/**
- * Called when the {@link HotwordDetectionService} is created by the system and given a
- * short amount of time to report its initialization state.
+ * Called when the {@link HotwordDetectionService} or {@link VisualQueryDetectionService} is
+ * created by the system and given a short amount of time to report their initialization
+ * state.
*
- * @param status Info about initialization state of {@link HotwordDetectionService}; the
- * allowed values are {@link SandboxedDetectionServiceBase#INITIALIZATION_STATUS_SUCCESS},
+ * @param status Info about initialization state of {@link HotwordDetectionService} or
+ * {@link VisualQueryDetectionService}; allowed values are
+ * {@link SandboxedDetectionServiceBase#INITIALIZATION_STATUS_SUCCESS},
* 1<->{@link SandboxedDetectionServiceBase#getMaxCustomInitializationStatus()},
* {@link SandboxedDetectionServiceBase#INITIALIZATION_STATUS_UNKNOWN}.
*/
void onHotwordDetectionServiceInitialized(int status);
/**
- * Called with the {@link HotwordDetectionService} is restarted.
+ * Called with the {@link HotwordDetectionService} or {@link VisualQueryDetectionService} is
+ * restarted.
*
* Clients are expected to call {@link HotwordDetector#updateState} to share the state with
* the newly created service.
diff --git a/core/java/android/service/voice/IDetectorSessionVisualQueryDetectionCallback.aidl b/core/java/android/service/voice/IDetectorSessionVisualQueryDetectionCallback.aidl
new file mode 100644
index 0000000..22172ed
--- /dev/null
+++ b/core/java/android/service/voice/IDetectorSessionVisualQueryDetectionCallback.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.voice;
+
+/**
+ * Callback for returning the detected result from the {@link VisualQueryDetectionService}.
+ *
+ * The {@link VisualQueryDetectorSession} will overrides this interface to reach query egression
+ * control within each callback methods.
+ *
+ * @hide
+ */
+oneway interface IDetectorSessionVisualQueryDetectionCallback {
+
+ /**
+ * Called when the user attention is gained and intent to show the assistant icon in SysUI.
+ */
+ void onAttentionGained();
+
+ /**
+ * Called when the user attention is lost and intent to hide the assistant icon in SysUI.
+ */
+ void onAttentionLost();
+
+ /**
+ * Called when the detected query is streamed.
+ */
+ void onQueryDetected(in String partialQuery);
+
+ /**
+ * Called when the detected result is valid.
+ */
+ void onQueryFinished();
+
+ /**
+ * Called when the detected result is invalid.
+ */
+ void onQueryRejected();
+}
diff --git a/core/java/android/service/voice/ISandboxedDetectionService.aidl b/core/java/android/service/voice/ISandboxedDetectionService.aidl
index 5537fd1..098536d 100644
--- a/core/java/android/service/voice/ISandboxedDetectionService.aidl
+++ b/core/java/android/service/voice/ISandboxedDetectionService.aidl
@@ -24,6 +24,7 @@
import android.os.ParcelFileDescriptor;
import android.os.PersistableBundle;
import android.os.SharedMemory;
+import android.service.voice.IDetectorSessionVisualQueryDetectionCallback;
import android.service.voice.IDspHotwordDetectionCallback;
import android.view.contentcapture.IContentCaptureManager;
import android.speech.IRecognitionServiceManager;
@@ -47,6 +48,8 @@
in PersistableBundle options,
in IDspHotwordDetectionCallback callback);
+ void detectWithVisualSignals(in IDetectorSessionVisualQueryDetectionCallback callback);
+
void updateState(
in PersistableBundle options,
in SharedMemory sharedMemory,
diff --git a/core/java/android/service/voice/IVisualQueryDetectionVoiceInteractionCallback.aidl b/core/java/android/service/voice/IVisualQueryDetectionVoiceInteractionCallback.aidl
new file mode 100644
index 0000000..2eb2470
--- /dev/null
+++ b/core/java/android/service/voice/IVisualQueryDetectionVoiceInteractionCallback.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.voice;
+
+import android.media.AudioFormat;
+
+/**
+ * Callback for returning the detected result from the VisualQueryDetectionService.
+ *
+ * @hide
+ */
+oneway interface IVisualQueryDetectionVoiceInteractionCallback {
+
+ /**
+ * Called when the detected query is streamed
+ */
+ void onQueryDetected(in String partialQuery);
+
+ /**
+ * Called when the detected result is valid.
+ */
+ void onQueryFinished();
+
+ /**
+ * Called when the detected result is invalid.
+ */
+ void onQueryRejected();
+
+ /**
+ * Called when the detection fails due to an error.
+ */
+ void onError();
+
+}
diff --git a/core/java/android/service/voice/IVoiceInteractionService.aidl b/core/java/android/service/voice/IVoiceInteractionService.aidl
index 24819a6..6a54606 100644
--- a/core/java/android/service/voice/IVoiceInteractionService.aidl
+++ b/core/java/android/service/voice/IVoiceInteractionService.aidl
@@ -16,6 +16,8 @@
package android.service.voice;
+import android.os.Bundle;
+
import com.android.internal.app.IVoiceActionCheckCallback;
/**
@@ -28,4 +30,6 @@
void launchVoiceAssistFromKeyguard();
void getActiveServiceSupportedActions(in List<String> voiceActions,
in IVoiceActionCheckCallback callback);
+ void prepareToShowSession(in Bundle args, int flags);
+ void showSessionFailed(in Bundle args);
}
diff --git a/core/java/android/service/voice/VisualQueryDetectionService.java b/core/java/android/service/voice/VisualQueryDetectionService.java
index d8266f3..fde0afb 100644
--- a/core/java/android/service/voice/VisualQueryDetectionService.java
+++ b/core/java/android/service/voice/VisualQueryDetectionService.java
@@ -36,6 +36,7 @@
import android.util.Log;
import android.view.contentcapture.IContentCaptureManager;
+import java.util.Objects;
import java.util.function.IntConsumer;
/**
@@ -80,6 +81,19 @@
private final ISandboxedDetectionService mInterface = new ISandboxedDetectionService.Stub() {
@Override
+ public void detectWithVisualSignals(
+ IDetectorSessionVisualQueryDetectionCallback callback) {
+ Log.v(TAG, "#detectWithVisualSignals");
+ VisualQueryDetectionService.this.onStartDetection(new Callback(callback));
+ }
+
+ @Override
+ public void stopDetection() {
+ Log.v(TAG, "#stopDetection");
+ VisualQueryDetectionService.this.onStopDetection();
+ }
+
+ @Override
public void updateState(PersistableBundle options, SharedMemory sharedMemory,
IRemoteCallback callback) throws RemoteException {
Log.v(TAG, "#updateState" + (callback != null ? " with callback" : ""));
@@ -128,11 +142,6 @@
public void updateRecognitionServiceManager(IRecognitionServiceManager manager) {
Log.v(TAG, "Ignore #updateRecognitionServiceManager");
}
-
- @Override
- public void stopDetection() {
- throw new UnsupportedOperationException("Not supported by VisualQueryDetectionService");
- }
};
/**
@@ -190,9 +199,118 @@
/**
* Callback for sending out signals and returning query results.
+ *
+ * On successful user attention, developers should call {@link Callback#onAttentionGained()}
+ * to enable the streaming of the query.
+ * <p>
+ * On user attention is lost, developers should call {@link Callback#onAttentionLost()} to
+ * disable the streaming of the query.
+ * <p>
+ * On query is detected and ready to stream, developers should call
+ * {@link Callback#onQueryDetected(String)} to return detected query to the
+ * {@link VisualQueryDetector}.
+ * <p>
+ * On streamed query should be rejected, clients should call {@link Callback#onQueryRejected()}
+ * to abandon query streamed to the {@link VisualQueryDetector}.
+ * <p>
+ * On streamed query is finished, clients should call {@link Callback#onQueryFinished()} to
+ * complete query streamed to {@link VisualQueryDetector}.
+ * <p>
+ * Before a call for {@link Callback#onQueryDetected(String)} is triggered,
+ * {@link Callback#onAttentionGained()} MUST be called to enable the streaming of query. A query
+ * streaming is also expected to be finished by calling either
+ * {@link Callback#onQueryFinished()} or {@link Callback#onQueryRejected()} before a new query
+ * should start streaming. When the service enters the state where query streaming should be
+ * disabled, {@link Callback#onAttentionLost()} MUST be called to block unnecessary streaming.
*/
public static final class Callback {
- //TODO: Add callback to send signals to VIS and SysUI.
+
+ // TODO: consider making the constructor a test api for testing purpose
+ public Callback() {
+ mRemoteCallback = null;
+ }
+
+ private final IDetectorSessionVisualQueryDetectionCallback mRemoteCallback;
+
+ private Callback(IDetectorSessionVisualQueryDetectionCallback remoteCallback) {
+ mRemoteCallback = remoteCallback;
+ }
+
+ /**
+ * Informs attention listener that the user attention is gained.
+ */
+ public void onAttentionGained() {
+ try {
+ mRemoteCallback.onAttentionGained();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Informs attention listener that the user attention is lost.
+ */
+ public void onAttentionLost() {
+ try {
+ mRemoteCallback.onAttentionLost();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Informs the {@link VisualQueryDetector} with the text content being captured about the
+ * query from the audio source. {@code partialQuery} is provided to the
+ * {@link VisualQueryDetector}. This method is expected to be only triggered if
+ * {@link Callback#onAttentionGained()} is called to put the service into the attention
+ * gained state.
+ *
+ * @param partialQuery Partially detected query in string.
+ * @throws IllegalStateException if method called without attention gained.
+ */
+ public void onQueryDetected(@NonNull String partialQuery) throws IllegalStateException {
+ Objects.requireNonNull(partialQuery);
+ try {
+ mRemoteCallback.onQueryDetected(partialQuery);
+ } catch (RemoteException e) {
+ throw new IllegalStateException("#onQueryDetected must be only be triggered after "
+ + "calling #onAttentionGained to be in the attention gained state.");
+ }
+ }
+
+ /**
+ * Informs the {@link VisualQueryDetector} to abandon the streamed partial query that has
+ * been sent to {@link VisualQueryDetector}.This method is expected to be only triggered if
+ * {@link Callback#onQueryDetected()} is called to put the service into the query streaming
+ * state.
+ *
+ * @throws IllegalStateException if method called without query streamed.
+ */
+ public void onQueryRejected() throws IllegalStateException {
+ try {
+ mRemoteCallback.onQueryRejected();
+ } catch (RemoteException e) {
+ throw new IllegalStateException("#onQueryRejected must be only be triggered after "
+ + "calling #onQueryDetected to be in the query streaming state.");
+ }
+ }
+
+ /**
+ * Informs {@link VisualQueryDetector} with the metadata to complete the streamed partial
+ * query that has been sent to {@link VisualQueryDetector}. This method is expected to be
+ * only triggered if {@link Callback#onQueryDetected()} is called to put the service into
+ * the query streaming state.
+ *
+ * @throws IllegalStateException if method called without query streamed.
+ */
+ public void onQueryFinished() throws IllegalStateException {
+ try {
+ mRemoteCallback.onQueryFinished();
+ } catch (RemoteException e) {
+ throw new IllegalStateException("#onQueryFinished must be only be triggered after "
+ + "calling #onQueryDetected to be in the query streaming state.");
+ }
+ }
}
}
diff --git a/core/java/android/service/voice/VisualQueryDetector.java b/core/java/android/service/voice/VisualQueryDetector.java
new file mode 100644
index 0000000..6917576
--- /dev/null
+++ b/core/java/android/service/voice/VisualQueryDetector.java
@@ -0,0 +1,377 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.voice;
+
+import static android.Manifest.permission.CAMERA;
+import static android.Manifest.permission.RECORD_AUDIO;
+
+import android.annotation.CallbackExecutor;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
+import android.hardware.soundtrigger.SoundTrigger;
+import android.media.AudioFormat;
+import android.os.Binder;
+import android.os.ParcelFileDescriptor;
+import android.os.PersistableBundle;
+import android.os.RemoteException;
+import android.os.SharedMemory;
+import android.util.Slog;
+
+import com.android.internal.app.IHotwordRecognitionStatusCallback;
+import com.android.internal.app.IVoiceInteractionManagerService;
+
+import java.io.PrintWriter;
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
+
+/**
+ * Manages VisualQueryDetectionService.
+ *
+ * This detector provides necessary functionalities to initialize, start, update and destroy a
+ * {@link VisualQueryDetectionService}.
+ *
+ * @hide
+ **/
+@SystemApi
+@SuppressLint("NotCloseable")
+public class VisualQueryDetector {
+ private static final String TAG = VisualQueryDetector.class.getSimpleName();
+ private static final boolean DEBUG = false;
+
+ private final Callback mCallback;
+ private final Executor mExecutor;
+ private final IVoiceInteractionManagerService mManagerService;
+ private final VisualQueryDetectorInitializationDelegate mInitializationDelegate;
+
+ VisualQueryDetector(
+ IVoiceInteractionManagerService managerService,
+ @NonNull @CallbackExecutor Executor executor,
+ Callback callback) {
+ mManagerService = managerService;
+ mCallback = callback;
+ mExecutor = executor;
+ mInitializationDelegate = new VisualQueryDetectorInitializationDelegate();
+ }
+
+ /**
+ * Initialize the {@link VisualQueryDetectionService} by passing configurations and read-only
+ * data.
+ */
+ void initialize(@Nullable PersistableBundle options, @Nullable SharedMemory sharedMemory) {
+ mInitializationDelegate.initialize(options, sharedMemory);
+ }
+
+ /**
+ * Set configuration and pass read-only data to {@link VisualQueryDetectionService}.
+ *
+ * @see HotwordDetector#updateState(PersistableBundle, SharedMemory)
+ */
+ public void updateState(@Nullable PersistableBundle options,
+ @Nullable SharedMemory sharedMemory) throws
+ HotwordDetector.IllegalDetectorStateException {
+ mInitializationDelegate.updateState(options, sharedMemory);
+ }
+
+
+ /**
+ * On calling this method, {@link VisualQueryDetectionService
+ * #onStartDetection(VisualQueryDetectionService.Callback)} will be called to start using
+ * visual signals such as camera frames and microphone audio to perform detection. When user
+ * attention is captured and the {@link VisualQueryDetectionService} streams queries,
+ * {@link VisualQueryDetector.Callback#onQueryDetected(String)} is called to control the
+ * behavior of handling {@code transcribedText}. When the query streaming is finished,
+ * {@link VisualQueryDetector.Callback#onQueryFinished()} is called. If the current streamed
+ * query is invalid, {@link VisualQueryDetector.Callback#onQueryRejected()} is called to abandon
+ * the streamed query.
+ *
+ * @see HotwordDetector#startRecognition()
+ */
+ @RequiresPermission(allOf = {CAMERA, RECORD_AUDIO})
+ public boolean startRecognition() throws HotwordDetector.IllegalDetectorStateException {
+ if (DEBUG) {
+ Slog.i(TAG, "#startRecognition");
+ }
+ // check if the detector is active with the initialization delegate
+ mInitializationDelegate.startRecognition();
+
+ try {
+ mManagerService.startPerceiving(new BinderCallback(mExecutor, mCallback));
+ } catch (SecurityException e) {
+ Slog.e(TAG, "startRecognition failed: " + e);
+ return false;
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ return true;
+ }
+
+ /**
+ * Stops visual query detection recognition.
+ *
+ * @see HotwordDetector#stopRecognition()
+ */
+ @RequiresPermission(allOf = {CAMERA, RECORD_AUDIO})
+ public boolean stopRecognition() throws HotwordDetector.IllegalDetectorStateException {
+ if (DEBUG) {
+ Slog.i(TAG, "#stopRecognition");
+ }
+ // check if the detector is active with the initialization delegate
+ mInitializationDelegate.startRecognition();
+
+ try {
+ mManagerService.stopPerceiving();
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ return true;
+ }
+
+ /**
+ * Destroy the current detector.
+ *
+ * @see HotwordDetector#destroy()
+ */
+ public void destroy() {
+ if (DEBUG) {
+ Slog.i(TAG, "#destroy");
+ }
+ mInitializationDelegate.destroy();
+ }
+
+ /** @hide */
+ public void dump(String prefix, PrintWriter pw) {
+ // TODO: implement this
+ }
+
+ /** @hide */
+ public HotwordDetector getInitializationDelegate() {
+ return mInitializationDelegate;
+ }
+
+ /** @hide */
+ void registerOnDestroyListener(Consumer<AbstractDetector> onDestroyListener) {
+ mInitializationDelegate.registerOnDestroyListener(onDestroyListener);
+ }
+
+ /**
+ * A class that lets a VoiceInteractionService implementation interact with
+ * visual query detection APIs.
+ */
+ public interface Callback {
+
+ /**
+ * Called when the {@link VisualQueryDetectionService} starts to stream partial queries.
+ *
+ * @param partialQuery The partial query in a text form being streamed.
+ */
+ void onQueryDetected(@NonNull String partialQuery);
+
+ /**
+ * Called when the {@link VisualQueryDetectionService} decides to abandon the streamed
+ * partial queries.
+ */
+ void onQueryRejected();
+
+ /**
+ * Called when the {@link VisualQueryDetectionService} finishes streaming partial queries.
+ */
+ void onQueryFinished();
+
+ /**
+ * Called when the {@link VisualQueryDetectionService} is created by the system and given a
+ * short amount of time to report its initialization state.
+ *
+ * @param status Info about initialization state of {@link VisualQueryDetectionService}; the
+ * allowed values are {@link SandboxedDetectionServiceBase#INITIALIZATION_STATUS_SUCCESS},
+ * 1<->{@link SandboxedDetectionServiceBase#getMaxCustomInitializationStatus()},
+ * {@link SandboxedDetectionServiceBase#INITIALIZATION_STATUS_UNKNOWN}.
+ */
+ void onVisualQueryDetectionServiceInitialized(int status);
+
+ /**
+ * Called with the {@link VisualQueryDetectionService} is restarted.
+ *
+ * Clients are expected to call {@link HotwordDetector#updateState} to share the state with
+ * the newly created service.
+ */
+ void onVisualQueryDetectionServiceRestarted();
+
+ /**
+ * Called when the detection fails due to an error.
+ */
+ //TODO(b/265390855): Replace this callback with the new onError(DetectorError) design.
+ void onError();
+ }
+
+ private class VisualQueryDetectorInitializationDelegate extends AbstractDetector {
+
+ VisualQueryDetectorInitializationDelegate() {
+ super(mManagerService, null);
+ }
+
+ @Override
+ void initialize(@Nullable PersistableBundle options, @Nullable SharedMemory sharedMemory) {
+ initAndVerifyDetector(options, sharedMemory,
+ new InitializationStateListener(mExecutor, mCallback),
+ DETECTOR_TYPE_VISUAL_QUERY_DETECTOR);
+ }
+
+ @Override
+ public boolean stopRecognition() throws IllegalDetectorStateException {
+ throwIfDetectorIsNoLongerActive();
+ return true;
+ }
+
+ @Override
+ public boolean startRecognition() throws IllegalDetectorStateException {
+ throwIfDetectorIsNoLongerActive();
+ return true;
+ }
+
+ @Override
+ public final boolean startRecognition(
+ @NonNull ParcelFileDescriptor audioStream,
+ @NonNull AudioFormat audioFormat,
+ @Nullable PersistableBundle options) throws IllegalDetectorStateException {
+ //No-op, not supported by VisualQueryDetector as it should be trusted.
+ return false;
+ }
+
+ @Override
+ public boolean isUsingSandboxedDetectionService() {
+ return true;
+ }
+ }
+
+ private static class BinderCallback
+ extends IVisualQueryDetectionVoiceInteractionCallback.Stub {
+ private final Executor mExecutor;
+ private final VisualQueryDetector.Callback mCallback;
+
+ BinderCallback(Executor executor, VisualQueryDetector.Callback callback) {
+ this.mExecutor = executor;
+ this.mCallback = callback;
+ }
+
+ /** Called when the detected result is valid. */
+ @Override
+ public void onQueryDetected(@NonNull String partialQuery) {
+ Slog.v(TAG, "BinderCallback#onQueryDetected");
+ Binder.withCleanCallingIdentity(() -> mExecutor.execute(
+ () -> mCallback.onQueryDetected(partialQuery)));
+ }
+
+ @Override
+ public void onQueryFinished() {
+ Slog.v(TAG, "BinderCallback#onQueryFinished");
+ Binder.withCleanCallingIdentity(() -> mExecutor.execute(
+ () -> mCallback.onQueryFinished()));
+ }
+
+ @Override
+ public void onQueryRejected() {
+ Slog.v(TAG, "BinderCallback#onQueryRejected");
+ Binder.withCleanCallingIdentity(() -> mExecutor.execute(
+ () -> mCallback.onQueryRejected()));
+ }
+
+ /** Called when the detection fails due to an error. */
+ @Override
+ public void onError() {
+ Slog.v(TAG, "BinderCallback#onError");
+ Binder.withCleanCallingIdentity(() -> mExecutor.execute(
+ () -> mCallback.onError()));
+ }
+
+ }
+
+
+ private static class InitializationStateListener
+ extends IHotwordRecognitionStatusCallback.Stub {
+ private final Executor mExecutor;
+ private final Callback mCallback;
+
+ InitializationStateListener(Executor executor, Callback callback) {
+ this.mExecutor = executor;
+ this.mCallback = callback;
+ }
+
+ @Override
+ public void onKeyphraseDetected(
+ SoundTrigger.KeyphraseRecognitionEvent recognitionEvent,
+ HotwordDetectedResult result) {
+ if (DEBUG) {
+ Slog.i(TAG, "Ignored #onKeyphraseDetected event");
+ }
+ }
+
+ @Override
+ public void onGenericSoundTriggerDetected(
+ SoundTrigger.GenericRecognitionEvent recognitionEvent) throws RemoteException {
+ if (DEBUG) {
+ Slog.i(TAG, "Ignored #onGenericSoundTriggerDetected event");
+ }
+ }
+
+ @Override
+ public void onRejected(HotwordRejectedResult result) throws RemoteException {
+ if (DEBUG) {
+ Slog.i(TAG, "Ignored #onRejected event");
+ }
+ }
+
+ @Override
+ public void onRecognitionPaused() throws RemoteException {
+ if (DEBUG) {
+ Slog.i(TAG, "Ignored #onRecognitionPaused event");
+ }
+ }
+
+ @Override
+ public void onRecognitionResumed() throws RemoteException {
+ if (DEBUG) {
+ Slog.i(TAG, "Ignored #onRecognitionResumed event");
+ }
+ }
+
+ @Override
+ public void onStatusReported(int status) {
+ Slog.v(TAG, "onStatusReported" + (DEBUG ? "(" + status + ")" : ""));
+ //TODO: rename the target callback with a more general term
+ Binder.withCleanCallingIdentity(() -> mExecutor.execute(
+ () -> mCallback.onVisualQueryDetectionServiceInitialized(status)));
+
+ }
+
+ @Override
+ public void onProcessRestarted() throws RemoteException {
+ Slog.v(TAG, "onProcessRestarted()");
+ //TODO: rename the target callback with a more general term
+ Binder.withCleanCallingIdentity(() -> mExecutor.execute(
+ () -> mCallback.onVisualQueryDetectionServiceRestarted()));
+ }
+
+ @Override
+ public void onError(int status) throws RemoteException {
+ Slog.v(TAG, "Initialization Error: (" + status + ")");
+ // Do nothing
+ }
+ }
+}
diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java
index 9e1518d..df739e3 100644
--- a/core/java/android/service/voice/VoiceInteractionService.java
+++ b/core/java/android/service/voice/VoiceInteractionService.java
@@ -17,6 +17,7 @@
package android.service.voice;
import android.Manifest;
+import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -58,7 +59,7 @@
import java.util.Locale;
import java.util.Objects;
import java.util.Set;
-
+import java.util.concurrent.Executor;
/**
* Top-level service of the current global voice interactor, which is providing
* support for hotwording, the back-end of a {@link android.app.VoiceInteractor}, etc.
@@ -94,6 +95,20 @@
public static final String SERVICE_META_DATA = "android.voice_interaction";
/**
+ * Bundle key used to specify the id when the system prepares to show session. It increases for
+ * each request.
+ * <p>
+ * Type: int
+ * </p>
+ * @see #showSession(Bundle, int)
+ * @see #onPrepareToShowSession(Bundle, int)
+ * @see #onShowSessionFailed(Bundle)
+ * @see VoiceInteractionSession#onShow(Bundle, int)
+ * @see VoiceInteractionSession#show(Bundle, int)
+ */
+ public static final String KEY_SHOW_SESSION_ID = "android.service.voice.SHOW_SESSION_ID";
+
+ /**
* For apps targeting Build.VERSION_CODES.TRAMISU and above, implementors of this
* service can create multiple AlwaysOnHotwordDetector instances in parallel. They will
* also e ale to create a single SoftwareHotwordDetector in parallel with any other
@@ -160,10 +175,26 @@
voiceActions,
callback));
}
+
+ @Override
+ public void prepareToShowSession(Bundle args, int flags) {
+ Handler.getMain().executeOrSendMessage(PooledLambda.obtainMessage(
+ VoiceInteractionService::onPrepareToShowSession,
+ VoiceInteractionService.this, args, flags));
+ }
+
+ @Override
+ public void showSessionFailed(@NonNull Bundle args) {
+ Handler.getMain().executeOrSendMessage(PooledLambda.obtainMessage(
+ VoiceInteractionService::onShowSessionFailed,
+ VoiceInteractionService.this, args));
+ }
};
IVoiceInteractionManagerService mSystemService;
+ private VisualQueryDetector mActiveVisualQueryDetector;
+
private final Object mLock = new Object();
private KeyphraseEnrollmentInfo mKeyphraseEnrollmentInfo;
@@ -184,6 +215,34 @@
}
/**
+ * Notify the interactor when the system prepares to show session. The system is going to
+ * bind the session service.
+ *
+ * @param args The arguments that were supplied to {@link #showSession(Bundle, int)}.
+ * It always includes {@link #KEY_SHOW_SESSION_ID}.
+ * @param flags The show flags originally provided to {@link #showSession(Bundle, int)}.
+ * @see #showSession(Bundle, int)
+ * @see #onShowSessionFailed(Bundle)
+ * @see VoiceInteractionSession#onShow(Bundle, int)
+ * @see VoiceInteractionSession#show(Bundle, int)
+ */
+ public void onPrepareToShowSession(@NonNull Bundle args, int flags) {
+ }
+
+ /**
+ * Called when the show session failed. E.g. When the system bound the session service failed.
+ *
+ * @param args Additional info about the show session attempt that failed. For now, includes
+ * {@link #KEY_SHOW_SESSION_ID}.
+ * @see #showSession(Bundle, int)
+ * @see #onPrepareToShowSession(Bundle, int)
+ * @see VoiceInteractionSession#onShow(Bundle, int)
+ * @see VoiceInteractionSession#show(Bundle, int)
+ */
+ public void onShowSessionFailed(@NonNull Bundle args) {
+ }
+
+ /**
* Check whether the given service component is the currently active
* VoiceInteractionService.
*/
@@ -544,6 +603,85 @@
}
/**
+ * Creates a {@link VisualQueryDetector} and initializes the application's
+ * {@link VisualQueryDetectionService} using {@code options} and {@code sharedMemory}.
+ *
+ * <p>To be able to call this, you need to set android:visualQueryDetectionService in the
+ * android.voice_interaction metadata file to a valid visual query detection service, and set
+ * android:isolatedProcess="true" in the service's declaration. Otherwise, this throws an
+ * {@link IllegalStateException}.
+ *
+ * <p>Using this has a noticeable impact on battery, since the microphone is kept open
+ * for the lifetime of the recognition {@link VisualQueryDetector#startRecognition() session}.
+ *
+ * @param options Application configuration data to be provided to the
+ * {@link VisualQueryDetectionService}. PersistableBundle does not allow any remotable objects
+ * or other contents that can be used to communicate with other processes.
+ * @param sharedMemory The unrestricted data blob to be provided to the
+ * {@link VisualQueryDetectionService}. Use this to provide models or other such data to the
+ * sandboxed process.
+ * @param callback The callback to notify of detection events.
+ * @return An instanece of {@link VisualQueryDetector}.
+ * @throws UnsupportedOperationException if only single detector is supported. Multiple detector
+ * is only available for apps targeting {@link Build.VERSION_CODES#TIRAMISU} and above.
+ * @throws IllegalStateException when there is an existing {@link VisualQueryDetector}, or when
+ * there is a non-trusted hotword detector running.
+ *
+ * @hide
+ */
+ // TODO: add MANAGE_HOTWORD_DETECTION permission to protect this API and update java doc.
+ @SystemApi
+ @NonNull
+ public final VisualQueryDetector createVisualQueryDetector(
+ @Nullable PersistableBundle options,
+ @Nullable SharedMemory sharedMemory,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull VisualQueryDetector.Callback callback) {
+ Objects.requireNonNull(executor);
+ Objects.requireNonNull(callback);
+
+ if (mSystemService == null) {
+ throw new IllegalStateException("Not available until onReady() is called");
+ }
+ synchronized (mLock) {
+ if (!CompatChanges.isChangeEnabled(MULTIPLE_ACTIVE_HOTWORD_DETECTORS)) {
+ throw new UnsupportedOperationException("VisualQueryDetector is only available if "
+ + "multiple detectors are allowed");
+ } else {
+ if (mActiveVisualQueryDetector != null) {
+ throw new IllegalStateException(
+ "There is already an active VisualQueryDetector. "
+ + "It must be destroyed to create a new one.");
+ }
+ for (HotwordDetector detector : mActiveDetectors) {
+ if (!detector.isUsingSandboxedDetectionService()) {
+ throw new IllegalStateException(
+ "It disallows to create trusted and non-trusted detectors "
+ + "at the same time.");
+ }
+ }
+ }
+
+ VisualQueryDetector visualQueryDetector =
+ new VisualQueryDetector(mSystemService, executor, callback);
+ HotwordDetector visualQueryDetectorInitializationDelegate =
+ visualQueryDetector.getInitializationDelegate();
+ mActiveDetectors.add(visualQueryDetectorInitializationDelegate);
+
+ try {
+ visualQueryDetector.registerOnDestroyListener(this::onHotwordDetectorDestroyed);
+ visualQueryDetector.initialize(options, sharedMemory);
+ } catch (Exception e) {
+ mActiveDetectors.remove(visualQueryDetectorInitializationDelegate);
+ visualQueryDetector.destroy();
+ throw e;
+ }
+ mActiveVisualQueryDetector = visualQueryDetector;
+ return visualQueryDetector;
+ }
+ }
+
+ /**
* Creates an {@link KeyphraseModelManager} to use for enrolling voice models outside of the
* pre-bundled system voice models.
* @hide
@@ -598,6 +736,10 @@
private void onHotwordDetectorDestroyed(@NonNull HotwordDetector detector) {
synchronized (mLock) {
+ if (mActiveVisualQueryDetector != null
+ && detector == mActiveVisualQueryDetector.getInitializationDelegate()) {
+ mActiveVisualQueryDetector = null;
+ }
mActiveDetectors.remove(detector);
shutdownHotwordDetectionServiceIfRequiredLocked();
}
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index 2c70229..d55fede 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -1763,7 +1763,8 @@
* @param args The arguments that were supplied to
* {@link VoiceInteractionService#showSession VoiceInteractionService.showSession}.
* Some example keys include : "invocation_type", "invocation_phone_state",
- * "invocation_time_ms", Intent.EXTRA_TIME ("android.intent.extra.TIME") indicating timing
+ * {@link VoiceInteractionService#KEY_SHOW_SESSION_ID}, "invocation_time_ms",
+ * Intent.EXTRA_TIME ("android.intent.extra.TIME") indicating timing
* in milliseconds of the KeyEvent that triggered Assistant and
* Intent.EXTRA_ASSIST_INPUT_DEVICE_ID (android.intent.extra.ASSIST_INPUT_DEVICE_ID)
* referring to the device that sent the request.
diff --git a/core/java/android/text/SegmentFinder.java b/core/java/android/text/SegmentFinder.java
index be0094b..047d07a 100644
--- a/core/java/android/text/SegmentFinder.java
+++ b/core/java/android/text/SegmentFinder.java
@@ -74,7 +74,7 @@
/**
* The default {@link SegmentFinder} implementation based on given segment ranges.
*/
- public static class DefaultSegmentFinder extends SegmentFinder {
+ public static class PrescribedSegmentFinder extends SegmentFinder {
private final int[] mSegments;
/**
@@ -87,7 +87,7 @@
* @throws IllegalArgumentException if the given segments array's length is not even; the
* given segments are not sorted or there are segments overlap with others.
*/
- public DefaultSegmentFinder(@NonNull int[] segments) {
+ public PrescribedSegmentFinder(@NonNull int[] segments) {
checkSegmentsValid(segments);
mSegments = segments;
}
diff --git a/core/java/android/text/TextShaper.java b/core/java/android/text/TextShaper.java
index a1d6cc8..6da0b63 100644
--- a/core/java/android/text/TextShaper.java
+++ b/core/java/android/text/TextShaper.java
@@ -173,7 +173,7 @@
private TextShaper() {}
/**
- * An consumer interface for accepting text shape result.
+ * A consumer interface for accepting text shape result.
*/
public interface GlyphsConsumer {
/**
diff --git a/core/java/android/view/ImeInsetsSourceConsumer.java b/core/java/android/view/ImeInsetsSourceConsumer.java
index e89be47..3e84153 100644
--- a/core/java/android/view/ImeInsetsSourceConsumer.java
+++ b/core/java/android/view/ImeInsetsSourceConsumer.java
@@ -123,7 +123,7 @@
// TODO: ResultReceiver for IME.
// TODO: Set mShowOnNextImeRender to automatically show IME and guard it with a flag.
- ImeTracker.get().onProgress(statsToken,
+ ImeTracker.forLogging().onProgress(statsToken,
ImeTracker.PHASE_CLIENT_INSETS_CONSUMER_REQUEST_SHOW);
if (getControl() == null) {
@@ -164,12 +164,13 @@
// - we do already have one, but we have control and use the passed in token
// for the insets animation already.
if (statsToken == null || getControl() != null) {
- statsToken = ImeTracker.get().onRequestHide(null /* component */, Process.myUid(),
+ statsToken = ImeTracker.forLogging().onRequestHide(null /* component */,
+ Process.myUid(),
ImeTracker.ORIGIN_CLIENT_HIDE_SOFT_INPUT,
SoftInputShowHideReason.HIDE_SOFT_INPUT_BY_INSETS_API);
}
- ImeTracker.get().onProgress(statsToken,
+ ImeTracker.forLogging().onProgress(statsToken,
ImeTracker.PHASE_CLIENT_INSETS_CONSUMER_NOTIFY_HIDDEN);
getImm().notifyImeHidden(mController.getHost().getWindowToken(), statsToken);
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index 5a9a252..8683cc2 100644
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -555,6 +555,7 @@
private String mKeyboardLanguageTag = null;
private String mKeyboardLayoutType = null;
private boolean mSupportsUsi = false;
+ private List<MotionRange> mMotionRanges = new ArrayList<>();
/** @see InputDevice#getId() */
public Builder setId(int id) {
@@ -670,12 +671,50 @@
return this;
}
+ /** @see InputDevice#getMotionRanges() */
+ public Builder addMotionRange(int axis, int source,
+ float min, float max, float flat, float fuzz, float resolution) {
+ mMotionRanges.add(new MotionRange(axis, source, min, max, flat, fuzz, resolution));
+ return this;
+ }
+
/** Build {@link InputDevice}. */
public InputDevice build() {
- return new InputDevice(mId, mGeneration, mControllerNumber, mName, mVendorId,
- mProductId, mDescriptor, mIsExternal, mSources, mKeyboardType, mKeyCharacterMap,
- mKeyboardLanguageTag, mKeyboardLayoutType, mHasVibrator, mHasMicrophone,
- mHasButtonUnderPad, mHasSensor, mHasBattery, mSupportsUsi);
+ InputDevice device = new InputDevice(
+ mId,
+ mGeneration,
+ mControllerNumber,
+ mName,
+ mVendorId,
+ mProductId,
+ mDescriptor,
+ mIsExternal,
+ mSources,
+ mKeyboardType,
+ mKeyCharacterMap,
+ mKeyboardLanguageTag,
+ mKeyboardLayoutType,
+ mHasVibrator,
+ mHasMicrophone,
+ mHasButtonUnderPad,
+ mHasSensor,
+ mHasBattery,
+ mSupportsUsi);
+
+ final int numRanges = mMotionRanges.size();
+ for (int i = 0; i < numRanges; i++) {
+ final MotionRange range = mMotionRanges.get(i);
+ device.addMotionRange(
+ range.getAxis(),
+ range.getSource(),
+ range.getMin(),
+ range.getMax(),
+ range.getFlat(),
+ range.getFuzz(),
+ range.getResolution());
+ }
+
+ return device;
}
}
@@ -1378,7 +1417,8 @@
out.writeInt(mHasBattery ? 1 : 0);
out.writeInt(mSupportsUsi ? 1 : 0);
- final int numRanges = mMotionRanges.size();
+ int numRanges = mMotionRanges.size();
+ numRanges = numRanges > MAX_RANGES ? MAX_RANGES : numRanges;
out.writeInt(numRanges);
for (int i = 0; i < numRanges; i++) {
MotionRange range = mMotionRanges.get(i);
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index 8e8e28a..c992450 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -26,6 +26,7 @@
import static android.view.WindowInsets.Type.LAST;
import static android.view.WindowInsets.Type.all;
import static android.view.WindowInsets.Type.ime;
+import static android.view.inputmethod.ImeTracker.PHASE_CLIENT_ANIMATION_CANCEL;
import android.animation.AnimationHandler;
import android.animation.Animator;
@@ -35,6 +36,8 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.ActivityThread;
+import android.content.Context;
import android.content.res.CompatibilityInfo;
import android.graphics.Insets;
import android.graphics.Rect;
@@ -60,6 +63,7 @@
import android.view.animation.LinearInterpolator;
import android.view.animation.PathInterpolator;
import android.view.inputmethod.ImeTracker;
+import android.view.inputmethod.ImeTracker.InputMethodJankContext;
import android.view.inputmethod.InputMethodManager;
import com.android.internal.annotations.VisibleForTesting;
@@ -186,6 +190,14 @@
@Nullable
String getRootViewTitle();
+ /**
+ * @return the context related to the rootView.
+ */
+ @Nullable
+ default Context getRootViewContext() {
+ return null;
+ }
+
/** @see ViewRootImpl#dipToPx */
int dipToPx(int dips);
@@ -306,7 +318,7 @@
@Retention(RetentionPolicy.SOURCE)
@IntDef(value = {ANIMATION_TYPE_NONE, ANIMATION_TYPE_SHOW, ANIMATION_TYPE_HIDE,
ANIMATION_TYPE_USER, ANIMATION_TYPE_RESIZE})
- @interface AnimationType {
+ public @interface AnimationType {
}
/**
@@ -321,6 +333,27 @@
/** Logging listener. */
private WindowInsetsAnimationControlListener mLoggingListener;
+ /** Context for {@link android.view.inputmethod.ImeTracker.ImeJankTracker} to monitor jank. */
+ private final InputMethodJankContext mJankContext = new InputMethodJankContext() {
+ @Override
+ public Context getDisplayContext() {
+ return mHost != null ? mHost.getRootViewContext() : null;
+ }
+
+ @Override
+ public SurfaceControl getTargetSurfaceControl() {
+ final InsetsSourceConsumer imeSourceConsumer = mSourceConsumers.get(ITYPE_IME);
+ final InsetsSourceControl imeSourceControl =
+ imeSourceConsumer != null ? imeSourceConsumer.getControl() : null;
+ return imeSourceControl != null ? imeSourceControl.getLeash() : null;
+ }
+
+ @Override
+ public String getHostPackageName() {
+ return mHost != null ? mHost.getRootViewContext().getPackageName() : null;
+ }
+ };
+
/**
* The default implementation of listener, to be used by InsetsController and InsetsPolicy to
* animate insets.
@@ -338,6 +371,7 @@
private final boolean mDisable;
private final int mFloatingImeBottomInset;
private final WindowInsetsAnimationControlListener mLoggingListener;
+ private final InputMethodJankContext mInputMethodJankContext;
private final ThreadLocal<AnimationHandler> mSfAnimationHandlerThreadLocal =
new ThreadLocal<AnimationHandler>() {
@@ -351,7 +385,8 @@
public InternalAnimationControlListener(boolean show, boolean hasAnimationCallbacks,
@InsetsType int requestedTypes, @Behavior int behavior, boolean disable,
- int floatingImeBottomInset, WindowInsetsAnimationControlListener loggingListener) {
+ int floatingImeBottomInset, WindowInsetsAnimationControlListener loggingListener,
+ @Nullable InputMethodJankContext jankContext) {
mShow = show;
mHasAnimationCallbacks = hasAnimationCallbacks;
mRequestedTypes = requestedTypes;
@@ -360,6 +395,7 @@
mDisable = disable;
mFloatingImeBottomInset = floatingImeBottomInset;
mLoggingListener = loggingListener;
+ mInputMethodJankContext = jankContext;
}
@Override
@@ -406,10 +442,26 @@
+ insetsFraction);
});
mAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ if (mInputMethodJankContext == null) return;
+ ImeTracker.forJank().onRequestAnimation(
+ mInputMethodJankContext,
+ mShow ? ANIMATION_TYPE_SHOW : ANIMATION_TYPE_HIDE,
+ !mHasAnimationCallbacks);
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ if (mInputMethodJankContext == null) return;
+ ImeTracker.forJank().onCancelAnimation();
+ }
@Override
public void onAnimationEnd(Animator animation) {
onAnimationFinish();
+ if (mInputMethodJankContext == null) return;
+ ImeTracker.forJank().onFinishAnimation();
}
});
if (!mHasAnimationCallbacks) {
@@ -873,7 +925,7 @@
/**
* @see InsetsState#calculateInsets(Rect, InsetsState, boolean, boolean, int, int, int, int,
- * int, SparseIntArray)
+ * int, android.util.SparseIntArray)
*/
@VisibleForTesting
public WindowInsets calculateInsets(boolean isScreenRound, boolean alwaysConsumeSystemBars,
@@ -981,7 +1033,7 @@
public void show(@InsetsType int types) {
ImeTracker.Token statsToken = null;
if ((types & ime()) != 0) {
- statsToken = ImeTracker.get().onRequestShow(null /* component */,
+ statsToken = ImeTracker.forLogging().onRequestShow(null /* component */,
Process.myUid(), ImeTracker.ORIGIN_CLIENT_SHOW_SOFT_INPUT,
SoftInputShowHideReason.SHOW_SOFT_INPUT_BY_INSETS_API);
}
@@ -1006,6 +1058,9 @@
}
// Handle pending request ready in case there was one set.
if (fromIme && mPendingImeControlRequest != null) {
+ if ((types & Type.ime()) != 0) {
+ ImeTracker.forLatency().onShown(statsToken, ActivityThread::currentApplication);
+ }
handlePendingControlRequest(statsToken);
return;
}
@@ -1028,7 +1083,7 @@
"show ignored for type: %d animType: %d requestedVisible: %s",
type, animationType, requestedVisible));
if (isImeAnimation) {
- ImeTracker.get().onCancelled(statsToken,
+ ImeTracker.forLogging().onCancelled(statsToken,
ImeTracker.PHASE_CLIENT_APPLY_ANIMATION);
}
continue;
@@ -1036,16 +1091,21 @@
if (fromIme && animationType == ANIMATION_TYPE_USER) {
// App is already controlling the IME, don't cancel it.
if (isImeAnimation) {
- ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_CLIENT_APPLY_ANIMATION);
+ ImeTracker.forLogging().onFailed(
+ statsToken, ImeTracker.PHASE_CLIENT_APPLY_ANIMATION);
}
continue;
}
if (isImeAnimation) {
- ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_APPLY_ANIMATION);
+ ImeTracker.forLogging().onProgress(
+ statsToken, ImeTracker.PHASE_CLIENT_APPLY_ANIMATION);
}
typesReady |= type;
}
if (DEBUG) Log.d(TAG, "show typesReady: " + typesReady);
+ if (fromIme && (typesReady & Type.ime()) != 0) {
+ ImeTracker.forLatency().onShown(statsToken, ActivityThread::currentApplication);
+ }
applyAnimation(typesReady, true /* show */, fromIme, statsToken);
}
@@ -1074,7 +1134,7 @@
public void hide(@InsetsType int types) {
ImeTracker.Token statsToken = null;
if ((types & ime()) != 0) {
- statsToken = ImeTracker.get().onRequestHide(null /* component */,
+ statsToken = ImeTracker.forLogging().onRequestHide(null /* component */,
Process.myUid(), ImeTracker.ORIGIN_CLIENT_HIDE_SOFT_INPUT,
SoftInputShowHideReason.HIDE_SOFT_INPUT_BY_INSETS_API);
}
@@ -1123,13 +1183,14 @@
// no-op: already hidden or animating out (because window visibility is
// applied before starting animation).
if (isImeAnimation) {
- ImeTracker.get().onCancelled(statsToken,
+ ImeTracker.forLogging().onCancelled(statsToken,
ImeTracker.PHASE_CLIENT_APPLY_ANIMATION);
}
continue;
}
if (isImeAnimation) {
- ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_APPLY_ANIMATION);
+ ImeTracker.forLogging().onProgress(
+ statsToken, ImeTracker.PHASE_CLIENT_APPLY_ANIMATION);
}
typesReady |= type;
}
@@ -1201,8 +1262,19 @@
@AnimationType int animationType,
@LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation,
boolean useInsetsAnimationThread, @Nullable ImeTracker.Token statsToken) {
- ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_CONTROL_ANIMATION);
+ ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_CONTROL_ANIMATION);
if ((types & mTypesBeingCancelled) != 0) {
+ final boolean monitoredAnimation =
+ animationType == ANIMATION_TYPE_SHOW || animationType == ANIMATION_TYPE_HIDE;
+ if (monitoredAnimation && (types & Type.ime()) != 0) {
+ if (animationType == ANIMATION_TYPE_SHOW) {
+ ImeTracker.forLatency().onShowCancelled(statsToken,
+ PHASE_CLIENT_ANIMATION_CANCEL, ActivityThread::currentApplication);
+ } else {
+ ImeTracker.forLatency().onHideCancelled(statsToken,
+ PHASE_CLIENT_ANIMATION_CANCEL, ActivityThread::currentApplication);
+ }
+ }
throw new IllegalStateException("Cannot start a new insets animation of "
+ Type.toString(types)
+ " while an existing " + Type.toString(mTypesBeingCancelled)
@@ -1214,7 +1286,7 @@
types &= ~mDisabledUserAnimationInsetsTypes;
if ((disabledTypes & ime()) != 0) {
- ImeTracker.get().onFailed(statsToken,
+ ImeTracker.forLogging().onFailed(statsToken,
ImeTracker.PHASE_CLIENT_DISABLED_USER_ANIMATION);
if (fromIme && !mState.getSource(mImeSourceConsumer.getId()).isVisible()) {
@@ -1235,7 +1307,8 @@
Trace.asyncTraceEnd(TRACE_TAG_VIEW, "IC.showRequestFromApiToImeReady", 0);
return;
}
- ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_DISABLED_USER_ANIMATION);
+ ImeTracker.forLogging().onProgress(statsToken,
+ ImeTracker.PHASE_CLIENT_DISABLED_USER_ANIMATION);
if (DEBUG) Log.d(TAG, "controlAnimation types: " + types);
mLastStartedAnimTypes |= types;
@@ -1302,8 +1375,11 @@
if ((typesReady & WindowInsets.Type.ime()) != 0) {
ImeTracing.getInstance().triggerClientDump("InsetsAnimationControlImpl",
mHost.getInputMethodManager(), null /* icProto */);
+ if (animationType == ANIMATION_TYPE_HIDE) {
+ ImeTracker.forLatency().onHidden(statsToken, ActivityThread::currentApplication);
+ }
}
- ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_ANIMATION_RUNNING);
+ ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_ANIMATION_RUNNING);
mRunningAnimations.add(new RunningAnimation(runner, animationType));
if (DEBUG) Log.d(TAG, "Animation added to runner. useInsetsAnimationThread: "
+ useInsetsAnimationThread);
@@ -1343,7 +1419,8 @@
private Pair<Integer, Boolean> collectSourceControls(boolean fromIme, @InsetsType int types,
SparseArray<InsetsSourceControl> controls, @AnimationType int animationType,
@Nullable ImeTracker.Token statsToken) {
- ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_COLLECT_SOURCE_CONTROLS);
+ ImeTracker.forLogging().onProgress(statsToken,
+ ImeTracker.PHASE_CLIENT_COLLECT_SOURCE_CONTROLS);
int typesReady = 0;
boolean imeReady = true;
@@ -1446,13 +1523,13 @@
}
final ImeTracker.Token statsToken = runner.getStatsToken();
if (shown) {
- ImeTracker.get().onProgress(statsToken,
+ ImeTracker.forLogging().onProgress(statsToken,
ImeTracker.PHASE_CLIENT_ANIMATION_FINISHED_SHOW);
- ImeTracker.get().onShown(statsToken);
+ ImeTracker.forLogging().onShown(statsToken);
} else {
- ImeTracker.get().onProgress(statsToken,
+ ImeTracker.forLogging().onProgress(statsToken,
ImeTracker.PHASE_CLIENT_ANIMATION_FINISHED_HIDE);
- ImeTracker.get().onHidden(statsToken);
+ ImeTracker.forLogging().onHidden(statsToken);
}
reportRequestedVisibleTypes();
}
@@ -1478,13 +1555,13 @@
private void cancelAnimation(InsetsAnimationControlRunner control, boolean invokeCallback) {
if (invokeCallback) {
- ImeTracker.get().onCancelled(control.getStatsToken(),
- ImeTracker.PHASE_CLIENT_ANIMATION_CANCEL);
+ ImeTracker.forLogging().onCancelled(control.getStatsToken(),
+ PHASE_CLIENT_ANIMATION_CANCEL);
control.cancel();
} else {
// Succeeds if invokeCallback is false (i.e. when called from notifyFinished).
- ImeTracker.get().onProgress(control.getStatsToken(),
- ImeTracker.PHASE_CLIENT_ANIMATION_CANCEL);
+ ImeTracker.forLogging().onProgress(control.getStatsToken(),
+ PHASE_CLIENT_ANIMATION_CANCEL);
}
if (DEBUG) {
Log.d(TAG, TextUtils.formatSimple(
@@ -1649,7 +1726,7 @@
final InternalAnimationControlListener listener = new InternalAnimationControlListener(
show, hasAnimationCallbacks, types, mHost.getSystemBarsBehavior(),
skipAnim || mAnimationsDisabled, mHost.dipToPx(FLOATING_IME_BOTTOM_INSET_DP),
- mLoggingListener);
+ mLoggingListener, mJankContext);
// We are about to playing the default animation (show/hide). Passing a null frame indicates
// the controlled types should be animated regardless of the frame.
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index b91019c..84bbdd1 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -1283,6 +1283,8 @@
* swipe gesture starts at X = 500 then moves to X = 400, this axis would have a value of
* -0.1.
* </ul>
+ * These values are relative to the state from the last event, not accumulated, so developers
+ * should make sure to process this axis value for all batched historical events.
*/
public static final int AXIS_GESTURE_X_OFFSET = 48;
@@ -1300,6 +1302,8 @@
* <li>For a touch pad, reports the distance that should be scrolled in the X axis as a result
* of the user's two-finger scroll gesture, in display pixels.
* </ul>
+ * These values are relative to the state from the last event, not accumulated, so developers
+ * should make sure to process this axis value for all batched historical events.
*/
public static final int AXIS_GESTURE_SCROLL_X_DISTANCE = 50;
@@ -1310,6 +1314,19 @@
*/
public static final int AXIS_GESTURE_SCROLL_Y_DISTANCE = 51;
+ /**
+ * Axis constant: pinch scale factor of a motion event.
+ * <p>
+ * <ul>
+ * <li>For a touch pad, reports the change in distance between the fingers when the user is
+ * making a pinch gesture, as a proportion of the previous distance. For example, if the fingers
+ * were 50 units apart and are now 52 units apart, the scale factor would be 1.04.
+ * </ul>
+ * These values are relative to the state from the last event, not accumulated, so developers
+ * should make sure to process this axis value for all batched historical events.
+ */
+ public static final int AXIS_GESTURE_PINCH_SCALE_FACTOR = 52;
+
// NOTE: If you add a new axis here you must also add it to:
// frameworks/native/include/android/input.h
// frameworks/native/libs/input/InputEventLabels.cpp
@@ -1369,6 +1386,7 @@
names.append(AXIS_GESTURE_Y_OFFSET, "AXIS_GESTURE_Y_OFFSET");
names.append(AXIS_GESTURE_SCROLL_X_DISTANCE, "AXIS_GESTURE_SCROLL_X_DISTANCE");
names.append(AXIS_GESTURE_SCROLL_Y_DISTANCE, "AXIS_GESTURE_SCROLL_Y_DISTANCE");
+ names.append(AXIS_GESTURE_PINCH_SCALE_FACTOR, "AXIS_GESTURE_PINCH_SCALE_FACTOR");
}
/**
@@ -1522,11 +1540,22 @@
*/
public static final int CLASSIFICATION_MULTI_FINGER_SWIPE = 4;
+ /**
+ * Classification constant: touchpad pinch.
+ *
+ * The current event stream represents the user pinching with two fingers on a touchpad. The
+ * gesture is centered around the current cursor position.
+ *
+ * @see #getClassification
+ */
+ public static final int CLASSIFICATION_PINCH = 5;
+
/** @hide */
@Retention(SOURCE)
@IntDef(prefix = { "CLASSIFICATION" }, value = {
CLASSIFICATION_NONE, CLASSIFICATION_AMBIGUOUS_GESTURE, CLASSIFICATION_DEEP_PRESS,
- CLASSIFICATION_TWO_FINGER_SWIPE, CLASSIFICATION_MULTI_FINGER_SWIPE})
+ CLASSIFICATION_TWO_FINGER_SWIPE, CLASSIFICATION_MULTI_FINGER_SWIPE,
+ CLASSIFICATION_PINCH})
public @interface Classification {};
/**
diff --git a/core/java/android/view/MotionPredictor.java b/core/java/android/view/MotionPredictor.java
index 3e58a31..fa86a4c 100644
--- a/core/java/android/view/MotionPredictor.java
+++ b/core/java/android/view/MotionPredictor.java
@@ -25,10 +25,15 @@
import java.util.List;
/**
- * Calculates motion predictions.
+ * Calculate motion predictions.
*
- * Add motions here to get predicted events!
- * @hide
+ * Feed motion events to this class in order to generate the predicted events. The prediction
+ * functionality may not be available on all devices. Check if a specific source is supported on a
+ * given input device using #isPredictionAvailable.
+ *
+ * Send all of the events that were received from the system here in order to generate complete,
+ * accurate predictions. When processing the returned predictions, make sure to consider all of the
+ * {@link MotionEvent#getHistoricalAxisValue historical samples}.
*/
// Acts as a pass-through to the native MotionPredictor object.
// Do not store any state in this Java layer, or add any business logic here. All of the
diff --git a/core/java/android/view/OWNERS b/core/java/android/view/OWNERS
index 6d64022..9e17620 100644
--- a/core/java/android/view/OWNERS
+++ b/core/java/android/view/OWNERS
@@ -40,6 +40,9 @@
per-file ScaleGestureDetector.java = file:/services/core/java/com/android/server/input/OWNERS
per-file KeyboardShortcut*.java = file:/services/core/java/com/android/server/input/OWNERS
per-file KeyCharacterMap.java = file:/services/core/java/com/android/server/input/OWNERS
+per-file VelocityTracker.java = file:/services/core/java/com/android/server/input/OWNERS
+per-file VerifiedInputEvent.java = file:/services/core/java/com/android/server/input/OWNERS
+per-file VerifiedInputEvent.aidl = file:/services/core/java/com/android/server/input/OWNERS
# InputWindowHandle
per-file InputWindowHandle.java = file:/services/core/java/com/android/server/input/OWNERS
diff --git a/core/java/android/view/VelocityTracker.java b/core/java/android/view/VelocityTracker.java
index 00170cb..85aea85 100644
--- a/core/java/android/view/VelocityTracker.java
+++ b/core/java/android/view/VelocityTracker.java
@@ -19,7 +19,6 @@
import android.annotation.IntDef;
import android.compat.annotation.UnsupportedAppUsage;
import android.hardware.input.InputManager;
-import android.os.Build;
import android.util.ArrayMap;
import android.util.Pools.SynchronizedPool;
@@ -190,8 +189,6 @@
private static native void nativeAddMovement(long ptr, MotionEvent event);
private static native void nativeComputeCurrentVelocity(long ptr, int units, float maxVelocity);
private static native float nativeGetVelocity(long ptr, int axis, int id);
- private static native boolean nativeGetEstimator(
- long ptr, int axis, int id, Estimator outEstimator);
private static native boolean nativeIsAxisSupported(int axis);
static {
@@ -436,7 +433,7 @@
* method:
* <ul>
* <li> {@link MotionEvent#AXIS_SCROLL}: supported starting
- * {@link Build.VERSION_CODES#UPSIDE_DOWN_CAKE}
+ * {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}
* </ul>
*
* <p>Before accessing velocities of an axis using this method, check that your
@@ -467,89 +464,4 @@
public float getAxisVelocity(@VelocityTrackableMotionEventAxis int axis) {
return nativeGetVelocity(mPtr, axis, ACTIVE_POINTER_ID);
}
-
- /**
- * Get an estimator for the movements of a pointer using past movements of the
- * pointer to predict future movements.
- *
- * It is not necessary to call {@link #computeCurrentVelocity(int)} before calling
- * this method.
- *
- * @param axis Which axis's velocity to return.
- * Should be one of the axes defined in {@link MotionEvent}.
- * @param id Which pointer's velocity to return.
- * @param outEstimator The estimator to populate.
- * @return True if an estimator was obtained, false if there is no information
- * available about the pointer.
- *
- * @hide For internal use only. Not a final API.
- */
- public boolean getEstimator(int axis, int id, Estimator outEstimator) {
- if (outEstimator == null) {
- throw new IllegalArgumentException("outEstimator must not be null");
- }
- return nativeGetEstimator(mPtr, axis, id, outEstimator);
- }
-
- /**
- * An estimator for the movements of a pointer based on a polynomial model.
- *
- * The last recorded position of the pointer is at time zero seconds.
- * Past estimated positions are at negative times and future estimated positions
- * are at positive times.
- *
- * First coefficient is position (in units), second is velocity (in units per second),
- * third is acceleration (in units per second squared).
- *
- * @hide For internal use only. Not a final API.
- */
- public static final class Estimator {
- // Must match VelocityTracker::Estimator::MAX_DEGREE
- private static final int MAX_DEGREE = 4;
-
- /**
- * Polynomial coefficients describing motion.
- */
- public final float[] coeff = new float[MAX_DEGREE + 1];
-
- /**
- * Polynomial degree, or zero if only position information is available.
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public int degree;
-
- /**
- * Confidence (coefficient of determination), between 0 (no fit) and 1 (perfect fit).
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public float confidence;
-
- /**
- * Gets an estimate of the position of the pointer at the specified time point.
- * @param time The time point in seconds, 0 is the last recorded time.
- * @return The estimated axis value.
- */
- public float estimate(float time) {
- return estimate(time, coeff);
- }
-
- /**
- * Gets the coefficient with the specified index.
- * @param index The index of the coefficient to return.
- * @return The coefficient, or 0 if the index is greater than the degree.
- */
- public float getCoeff(int index) {
- return index <= degree ? coeff[index] : 0;
- }
-
- private float estimate(float time, float[] c) {
- float a = 0;
- float scale = 1;
- for (int i = 0; i <= degree; i++) {
- a += c[i] * scale;
- scale *= time;
- }
- return a;
- }
- }
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 0198457..5ac9819 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -141,6 +141,7 @@
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.Transformation;
+import android.view.autofill.AutofillFeatureFlags;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillManager;
import android.view.autofill.AutofillValue;
@@ -3662,6 +3663,12 @@
* Indicates that the view enables auto handwriting initiation.
*/
private static final int PFLAG4_AUTO_HANDWRITING_ENABLED = 0x000010000;
+
+ /**
+ * Indicates that the view is important for Credential Manager.
+ */
+ private static final int PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER = 0x000020000;
+
/* End of masks for mPrivateFlags4 */
/** @hide */
@@ -6130,6 +6137,12 @@
setImportantForContentCapture(a.getInt(attr,
IMPORTANT_FOR_CONTENT_CAPTURE_AUTO));
}
+ break;
+ case R.styleable.View_isCredential:
+ if (a.peekValue(attr) != null) {
+ setIsCredential(a.getBoolean(attr, false));
+ }
+ break;
case R.styleable.View_defaultFocusHighlightEnabled:
if (a.peekValue(attr) != null) {
setDefaultFocusHighlightEnabled(a.getBoolean(attr, true));
@@ -10231,10 +10244,41 @@
return mContext.getSystemService(AutofillManager.class);
}
+ /**
+ * Check whether current activity / package is in denylist.If it's in the denylist,
+ * then the views marked as not important for autofill are not eligible for autofill.
+ */
+ final boolean isActivityDeniedForAutofillForUnimportantView() {
+ final AutofillManager afm = getAutofillManager();
+ // keep behavior same with denylist feature not enabled
+ if (afm == null) return true;
+ return afm.isActivityDeniedForAutofillForUnimportantView();
+ }
+
+ /**
+ * Check whether current view matches autofillable heuristics
+ */
+ final boolean isMatchingAutofillableHeuristics() {
+ final AutofillManager afm = getAutofillManager();
+ // keep default behavior
+ if (afm == null) return false;
+ return afm.isMatchingAutofillableHeuristics(this);
+ }
+
private boolean isAutofillable() {
if (getAutofillType() == AUTOFILL_TYPE_NONE) return false;
+ // Disable triggering autofill if the view is integrated with CredentialManager.
+ if (AutofillFeatureFlags.shouldIgnoreCredentialViews()
+ && isCredential()) return false;
+
if (!isImportantForAutofill()) {
+ // If view matches heuristics and is not denied, it will be treated same as view that's
+ // important for autofill
+ if (isMatchingAutofillableHeuristics()
+ && !isActivityDeniedForAutofillForUnimportantView()) {
+ return getAutofillViewId() > LAST_APP_AUTOFILL_ID;
+ }
// View is not important for "regular" autofill, so we must check if Augmented Autofill
// is enabled for the activity
final AutofillOptions options = mContext.getAutofillOptions();
@@ -31861,6 +31905,37 @@
}
/**
+ * Gets the mode for determining whether this view is a credential.
+ *
+ * <p>See {@link #isCredential()}.
+ *
+ * @param isCredential Whether the view is a credential.
+ *
+ * @attr ref android.R.styleable#View_isCredential
+ */
+ public void setIsCredential(boolean isCredential) {
+ if (isCredential) {
+ mPrivateFlags4 |= PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER;
+ } else {
+ mPrivateFlags4 &= ~PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER;
+ }
+ }
+
+ /**
+ * Gets the mode for determining whether this view is a credential.
+ *
+ * <p>See {@link #setIsCredential(boolean)}.
+ *
+ * @return false by default, or value passed to {@link #setIsCredential(boolean)}.
+ *
+ * @attr ref android.R.styleable#View_isCredential
+ */
+ public boolean isCredential() {
+ return ((mPrivateFlags4 & PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER)
+ == PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER);
+ }
+
+ /**
* Set whether this view enables automatic handwriting initiation.
*
* For a view with an active {@link InputConnection}, if auto handwriting is enabled then
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 46b2cfc..0e4ac01 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3723,7 +3723,9 @@
final View child = (preorderedList == null)
? mChildren[childIndex] : preorderedList.get(childIndex);
if ((flags & AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
- || child.isImportantForAutofill()) {
+ || child.isImportantForAutofill()
+ || (child.isMatchingAutofillableHeuristics()
+ && !child.isActivityDeniedForAutofillForUnimportantView())) {
list.add(child);
} else if (child instanceof ViewGroup) {
((ViewGroup) child).populateChildrenForAutofill(list, flags);
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index da9594b..2763607 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1426,7 +1426,7 @@
!= AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
if (registered) {
final AccessibilityWindowAttributes attributes = new AccessibilityWindowAttributes(
- mWindowAttributes);
+ mWindowAttributes, mContext.getResources().getConfiguration().getLocales());
if (!attributes.equals(mAccessibilityWindowAttributes)) {
mAccessibilityWindowAttributes = attributes;
mAccessibilityManager.setAccessibilityWindowAttributes(getDisplayId(),
@@ -5764,7 +5764,7 @@
}
case MSG_SHOW_INSETS: {
final ImeTracker.Token statsToken = (ImeTracker.Token) msg.obj;
- ImeTracker.get().onProgress(statsToken,
+ ImeTracker.forLogging().onProgress(statsToken,
ImeTracker.PHASE_CLIENT_HANDLE_SHOW_INSETS);
if (mView == null) {
Log.e(TAG,
@@ -5777,7 +5777,7 @@
}
case MSG_HIDE_INSETS: {
final ImeTracker.Token statsToken = (ImeTracker.Token) msg.obj;
- ImeTracker.get().onProgress(statsToken,
+ ImeTracker.forLogging().onProgress(statsToken,
ImeTracker.PHASE_CLIENT_HANDLE_HIDE_INSETS);
mInsetsController.hide(msg.arg1, msg.arg2 == 1, statsToken);
break;
@@ -8823,6 +8823,10 @@
mAdded = false;
AnimationHandler.removeRequestor(this);
}
+ if (mActiveSurfaceSyncGroup != null) {
+ mActiveSurfaceSyncGroup.markSyncReady();
+ mActiveSurfaceSyncGroup = null;
+ }
WindowManagerGlobal.getInstance().doRemoveView(this);
}
@@ -10320,10 +10324,10 @@
null /* icProto */);
}
if (viewAncestor != null) {
- ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_SHOW_INSETS);
+ ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_SHOW_INSETS);
viewAncestor.showInsets(types, fromIme, statsToken);
} else {
- ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_CLIENT_SHOW_INSETS);
+ ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_CLIENT_SHOW_INSETS);
}
}
@@ -10337,10 +10341,10 @@
null /* icProto */);
}
if (viewAncestor != null) {
- ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_HIDE_INSETS);
+ ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_HIDE_INSETS);
viewAncestor.hideInsets(types, fromIme, statsToken);
} else {
- ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_CLIENT_HIDE_INSETS);
+ ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_CLIENT_HIDE_INSETS);
}
}
diff --git a/core/java/android/view/ViewRootInsetsControllerHost.java b/core/java/android/view/ViewRootInsetsControllerHost.java
index c59d83e..037ce87 100644
--- a/core/java/android/view/ViewRootInsetsControllerHost.java
+++ b/core/java/android/view/ViewRootInsetsControllerHost.java
@@ -21,6 +21,7 @@
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_BEHAVIOR_CONTROLLED;
import android.annotation.NonNull;
+import android.content.Context;
import android.content.res.CompatibilityInfo;
import android.os.Handler;
import android.os.IBinder;
@@ -246,6 +247,11 @@
}
@Override
+ public Context getRootViewContext() {
+ return mViewRoot != null ? mViewRoot.getView().getContext() : null;
+ }
+
+ @Override
public int dipToPx(int dips) {
if (mViewRoot != null) {
return mViewRoot.dipToPx(dips);
diff --git a/core/java/android/view/WindowInfo.java b/core/java/android/view/WindowInfo.java
index 11d63c8..27dca0af 100644
--- a/core/java/android/view/WindowInfo.java
+++ b/core/java/android/view/WindowInfo.java
@@ -20,6 +20,7 @@
import android.graphics.Matrix;
import android.graphics.Region;
import android.os.IBinder;
+import android.os.LocaleList;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Pools;
@@ -60,6 +61,8 @@
public MagnificationSpec mMagnificationSpec = new MagnificationSpec();
+ public LocaleList locales = LocaleList.getEmptyLocaleList();
+
private WindowInfo() {
/* do nothing - hide constructor */
}
@@ -99,6 +102,7 @@
}
}
window.mMagnificationSpec.setTo(other.mMagnificationSpec);
+ window.locales = other.locales;
return window;
}
@@ -136,6 +140,7 @@
parcel.writeInt(0);
}
mMagnificationSpec.writeToParcel(parcel, flags);
+ parcel.writeParcelable(locales, flags);
}
@Override
@@ -160,6 +165,7 @@
matrix.setValues(mTransformMatrix);
builder.append(", mTransformMatrix=").append(matrix);
builder.append(", mMagnificationSpec=").append(mMagnificationSpec);
+ builder.append(", locales=").append(locales);
builder.append(']');
return builder.toString();
}
@@ -187,6 +193,7 @@
parcel.readBinderList(childTokens);
}
mMagnificationSpec = MagnificationSpec.CREATOR.createFromParcel(parcel);
+ locales = parcel.readParcelable(null, LocaleList.class);
}
private void clear() {
@@ -210,6 +217,7 @@
mMagnificationSpec.clear();
title = null;
accessibilityIdOfAnchor = AccessibilityNodeInfo.UNDEFINED_NODE_ID;
+ locales = LocaleList.getEmptyLocaleList();
}
public static final @android.annotation.NonNull Parcelable.Creator<WindowInfo> CREATOR =
diff --git a/core/java/android/view/accessibility/AccessibilityDisplayProxy.java b/core/java/android/view/accessibility/AccessibilityDisplayProxy.java
index a757236..dd320e1 100644
--- a/core/java/android/view/accessibility/AccessibilityDisplayProxy.java
+++ b/core/java/android/view/accessibility/AccessibilityDisplayProxy.java
@@ -83,7 +83,7 @@
* @param displayId the id of the display to proxy.
* @param executor the executor used to execute proxy callbacks.
* @param installedAndEnabledServices the list of infos representing the installed and
- * enabled a11y services.
+ * enabled accessibility services.
*/
public AccessibilityDisplayProxy(int displayId, @NonNull Executor executor,
@NonNull List<AccessibilityServiceInfo> installedAndEnabledServices) {
@@ -147,19 +147,27 @@
}
/**
- * Gets the focus of the window specified by {@code windowInfo}.
+ * Gets the node with focus, in this display.
*
- * @param windowInfo the window to search
- * @param focus The focus to find. One of {@link AccessibilityNodeInfo#FOCUS_INPUT} or
+ * <p>For {@link AccessibilityNodeInfo#FOCUS_INPUT}, this returns the input-focused node in the
+ * proxy display if this display can receive unspecified input events (input that does not
+ * specify a target display.)
+ *
+ * <p>For {@link AccessibilityNodeInfo#FOCUS_ACCESSIBILITY}, this returns the
+ * accessibility-focused node in the proxy display if the display has accessibility focus.
+ * @param focusType The focus to find. One of {@link AccessibilityNodeInfo#FOCUS_INPUT} or
* {@link AccessibilityNodeInfo#FOCUS_ACCESSIBILITY}.
* @return The node info of the focused view or null.
- * @hide
- * TODO(254545943): Do not expose until support for accessibility focus and/or input is in place
+
*/
@Nullable
- public AccessibilityNodeInfo findFocus(@NonNull AccessibilityWindowInfo windowInfo, int focus) {
- AccessibilityNodeInfo windowRoot = windowInfo.getRoot();
- return windowRoot != null ? windowRoot.findFocus(focus) : null;
+ public AccessibilityNodeInfo findFocus(int focusType) {
+ // TODO(264423198): Support querying the focused node of the proxy's display even if it is
+ // not the top-focused display and can't receive untargeted input events.
+ // TODO(254545943): Separate accessibility focus between proxy and phone state.
+ return AccessibilityInteractionClient.getInstance().findFocus(mConnectionId,
+ AccessibilityWindowInfo.ANY_WINDOW_ID, AccessibilityNodeInfo.ROOT_NODE_ID,
+ focusType);
}
/**
@@ -177,10 +185,10 @@
* Sets the list of {@link AccessibilityServiceInfo}s describing the services interested in the
* {@link AccessibilityDisplayProxy}'s display.
*
- * <p>These represent a11y features and services that are installed and running. These should
- * not include {@link AccessibilityService}s installed on the phone.
+ * <p>These represent accessibility features and services that are installed and running. These
+ * should not include {@link AccessibilityService}s installed on the phone.
*
- * @param installedAndEnabledServices the list of installed and running a11y services.
+ * @param installedAndEnabledServices the list of installed and running accessibility services.
*/
public void setInstalledAndEnabledServices(
@NonNull List<AccessibilityServiceInfo> installedAndEnabledServices) {
diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
index 52eda0a..83a6c5a 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -921,8 +921,6 @@
*
* @param connectionId The id of a connection for interacting with the system.
* @param accessibilityWindowId A unique window id. Use
- * {@link AccessibilityWindowInfo#ACTIVE_WINDOW_ID}
- * to query the currently active window. Use
* {@link AccessibilityWindowInfo#ANY_WINDOW_ID} to query all
* windows
* @param accessibilityNodeId A unique view id or virtual descendant id from
diff --git a/core/java/android/view/accessibility/AccessibilityWindowAttributes.java b/core/java/android/view/accessibility/AccessibilityWindowAttributes.java
index 562300c..92ed73b 100644
--- a/core/java/android/view/accessibility/AccessibilityWindowAttributes.java
+++ b/core/java/android/view/accessibility/AccessibilityWindowAttributes.java
@@ -17,11 +17,14 @@
package android.view.accessibility;
import android.annotation.NonNull;
+import android.os.LocaleList;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import android.view.WindowManager;
+import java.util.Objects;
+
/**
* This class represents the attributes of a window needed for {@link AccessibilityWindowInfo}.
*
@@ -30,13 +33,22 @@
public final class AccessibilityWindowAttributes implements Parcelable {
private final CharSequence mWindowTitle;
+ private final LocaleList mLocales;
- public AccessibilityWindowAttributes(@NonNull WindowManager.LayoutParams layoutParams) {
+ public AccessibilityWindowAttributes(@NonNull WindowManager.LayoutParams layoutParams,
+ @NonNull LocaleList locales) {
mWindowTitle = populateWindowTitle(layoutParams);
+ mLocales = locales;
}
private AccessibilityWindowAttributes(Parcel in) {
mWindowTitle = in.readCharSequence();
+ LocaleList inLocales = in.readParcelable(null, LocaleList.class);
+ if (inLocales != null) {
+ mLocales = inLocales;
+ } else {
+ mLocales = LocaleList.getEmptyLocaleList();
+ }
}
public CharSequence getWindowTitle() {
@@ -63,6 +75,10 @@
return windowTitle;
}
+ public @NonNull LocaleList getLocales() {
+ return mLocales;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -70,12 +86,13 @@
AccessibilityWindowAttributes that = (AccessibilityWindowAttributes) o;
- return TextUtils.equals(mWindowTitle, that.mWindowTitle);
+ return TextUtils.equals(mWindowTitle, that.mWindowTitle) && Objects.equals(
+ mLocales, that.mLocales);
}
@Override
public int hashCode() {
- return mWindowTitle.hashCode();
+ return Objects.hash(mWindowTitle, mLocales);
}
public static final Creator<AccessibilityWindowAttributes> CREATOR =
@@ -99,12 +116,14 @@
@Override
public void writeToParcel(@NonNull Parcel parcel, int flags) {
parcel.writeCharSequence(mWindowTitle);
+ parcel.writeParcelable(mLocales, flags);
}
@Override
public String toString() {
return "AccessibilityWindowAttributes{"
+ "mAccessibilityWindowTitle=" + mWindowTitle
+ + "mLocales=" + mLocales
+ '}';
}
}
diff --git a/core/java/android/view/accessibility/AccessibilityWindowInfo.java b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
index 9be9990..d84e0fb 100644
--- a/core/java/android/view/accessibility/AccessibilityWindowInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
@@ -23,6 +23,7 @@
import android.app.ActivityTaskManager;
import android.graphics.Rect;
import android.graphics.Region;
+import android.os.LocaleList;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemClock;
@@ -132,6 +133,8 @@
private int mConnectionId = UNDEFINED_CONNECTION_ID;
+ private LocaleList mLocales = LocaleList.getEmptyLocaleList();
+
/**
* Creates a new {@link AccessibilityWindowInfo}.
*/
@@ -555,6 +558,26 @@
}
/**
+ * Sets the locales of the window. Locales are populated by the view root by default.
+ *
+ * @param locales The {@link android.os.LocaleList}.
+ *
+ * @hide
+ */
+ public void setLocales(@NonNull LocaleList locales) {
+ mLocales = locales;
+ }
+
+ /**
+ * Return the {@link android.os.LocaleList} of the window.
+ *
+ * @return the locales of the window.
+ */
+ public @NonNull LocaleList getLocales() {
+ return mLocales;
+ }
+
+ /**
* Returns a cached instance if such is available or a new one is
* created.
*
@@ -676,6 +699,7 @@
}
parcel.writeInt(mConnectionId);
+ parcel.writeParcelable(mLocales, flags);
}
/**
@@ -706,6 +730,7 @@
}
mConnectionId = other.mConnectionId;
+ mLocales = other.mLocales;
}
private void initFromParcel(Parcel parcel) {
@@ -733,6 +758,7 @@
}
mConnectionId = parcel.readInt();
+ mLocales = parcel.readParcelable(null, LocaleList.class);
}
@Override
diff --git a/core/java/android/view/autofill/AutofillFeatureFlags.java b/core/java/android/view/autofill/AutofillFeatureFlags.java
new file mode 100644
index 0000000..cba399f
--- /dev/null
+++ b/core/java/android/view/autofill/AutofillFeatureFlags.java
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.autofill;
+
+import android.annotation.SuppressLint;
+import android.annotation.TestApi;
+import android.provider.DeviceConfig;
+import android.text.TextUtils;
+import android.util.ArraySet;
+import android.view.View;
+
+import com.android.internal.util.ArrayUtils;
+
+import java.util.Arrays;
+import java.util.Set;
+
+/**
+ * Feature flags associated with autofill.
+ * @hide
+ */
+@TestApi
+public class AutofillFeatureFlags {
+
+ /**
+ * {@code DeviceConfig} property used to set which Smart Suggestion modes for Augmented Autofill
+ * are available.
+ */
+ public static final String DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES =
+ "smart_suggestion_supported_modes";
+
+ /**
+ * Sets how long (in ms) the augmented autofill service is bound while idle.
+ *
+ * <p>Use {@code 0} to keep it permanently bound.
+ *
+ * @hide
+ */
+ public static final String DEVICE_CONFIG_AUGMENTED_SERVICE_IDLE_UNBIND_TIMEOUT =
+ "augmented_service_idle_unbind_timeout";
+
+ /**
+ * Sets how long (in ms) the augmented autofill service request is killed if not replied.
+ *
+ * @hide
+ */
+ public static final String DEVICE_CONFIG_AUGMENTED_SERVICE_REQUEST_TIMEOUT =
+ "augmented_service_request_timeout";
+
+ /**
+ * Sets allowed list for the autofill compatibility mode.
+ *
+ * The list of packages is {@code ":"} colon delimited, and each entry has the name of the
+ * package and an optional list of url bar resource ids (the list is delimited by
+ * brackets&mdash{@code [} and {@code ]}&mdash and is also comma delimited).
+ *
+ * <p>For example, a list with 3 packages {@code p1}, {@code p2}, and {@code p3}, where
+ * package {@code p1} have one id ({@code url_bar}, {@code p2} has none, and {@code p3 }
+ * have 2 ids {@code url_foo} and {@code url_bas}) would be
+ * {@code p1[url_bar]:p2:p3[url_foo,url_bas]}
+ */
+ public static final String DEVICE_CONFIG_AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES =
+ "compat_mode_allowed_packages";
+
+ /**
+ * Indicates Fill dialog feature enabled or not.
+ */
+ public static final String DEVICE_CONFIG_AUTOFILL_DIALOG_ENABLED =
+ "autofill_dialog_enabled";
+
+ /**
+ * Sets the autofill hints allowed list for the fields that can trigger the fill dialog
+ * feature at Activity starting.
+ *
+ * The list of autofill hints is {@code ":"} colon delimited.
+ *
+ * <p>For example, a list with 3 hints {@code password}, {@code phone}, and
+ * { @code emailAddress}, would be {@code password:phone:emailAddress}
+ *
+ * Note: By default the password field is enabled even there is no password hint in the list
+ *
+ * @see View#setAutofillHints(String...)
+ * @hide
+ */
+ public static final String DEVICE_CONFIG_AUTOFILL_DIALOG_HINTS =
+ "autofill_dialog_hints";
+
+ // START CREDENTIAL MANAGER FLAGS //
+
+ /**
+ * Indicates whether credential manager tagged views should be ignored from autofill structures.
+ * This flag is further gated by {@link #DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_ENABLED}
+ */
+ public static final String DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_IGNORE_VIEWS =
+ "autofill_credential_manager_ignore_views";
+
+ /**
+ * Indicates CredentialManager feature enabled or not.
+ * This is the overall feature flag. Individual behavior of credential manager may be controlled
+ * via a different flag, but gated by this flag.
+ */
+ public static final String DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_ENABLED =
+ "autofill_credential_manager_enabled";
+
+ /**
+ * Indicates whether credential manager tagged views should suppress fill dialog.
+ * This flag is further gated by {@link #DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_ENABLED}
+ *
+ * @hide
+ */
+ public static final String DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_SUPPRESS_FILL_DIALOG =
+ "autofill_credential_manager_suppress_fill_dialog";
+
+ /**
+ * Indicates whether credential manager tagged views should suppress save dialog.
+ * This flag is further gated by {@link #DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_ENABLED}
+ *
+ * @hide
+ */
+ public static final String DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_SUPPRESS_SAVE_DIALOG =
+ "autofill_credential_manager_suppress_save_dialog";
+ // END CREDENTIAL MANAGER FLAGS //
+
+ // START AUTOFILL FOR ALL APPS FLAGS //
+ /**
+ * Sets the list of activities and packages denied for autofill
+ *
+ * The list is {@code ";"} colon delimited. Activities under a package is separated by
+ * {@code ","}. Each package name much be followed by a {@code ":"}. Each package entry must be
+ * ends with a {@code ";"}
+ *
+ * <p>For example, a list with only 1 package would be, {@code Package1:;}. A list with one
+ * denied activity {@code Activity1} under {@code Package1} and a full denied package
+ * {@code Package2} would be {@code Package1:Activity1;Package2:;}
+ *
+ * @hide
+ */
+ @TestApi
+ public static final String DEVICE_CONFIG_PACKAGE_DENYLIST_FOR_UNIMPORTANT_VIEW =
+ "package_deny_list_for_unimportant_view";
+
+ /**
+ * Whether the heuristics check for view is enabled
+ *
+ * @hide
+ */
+ @TestApi
+ public static final String DEVICE_CONFIG_TRIGGER_FILL_REQUEST_ON_UNIMPORTANT_VIEW =
+ "trigger_fill_request_on_unimportant_view";
+
+ /**
+ * Continas imeAction ids that is irrelevant for autofill. For example, ime_action_search. We
+ * use this to avoid trigger fill request on unimportant views.
+ *
+ * The list is {@code ","} delimited.
+ *
+ * <p> For example, a imeAction list could be "2,3,4", corresponding to ime_action definition
+ * in {@link android.view.inputmethod.EditorInfo.java}</p>
+ *
+ * @hide
+ */
+ @TestApi
+ @SuppressLint("IntentName")
+ public static final String DEVICE_CONFIG_NON_AUTOFILLABLE_IME_ACTION_IDS =
+ "non_autofillable_ime_action_ids";
+ // END AUTOFILL FOR ALL APPS FLAGS //
+
+ /**
+ * Sets a value of delay time to show up the inline tooltip view.
+ *
+ * @hide
+ */
+ public static final String DEVICE_CONFIG_AUTOFILL_TOOLTIP_SHOW_UP_DELAY =
+ "autofill_inline_tooltip_first_show_delay";
+
+ private static final String DIALOG_HINTS_DELIMITER = ":";
+
+ private static final boolean DEFAULT_HAS_FILL_DIALOG_UI_FEATURE = false;
+ private static final String DEFAULT_FILL_DIALOG_ENABLED_HINTS = "";
+
+ // CREDENTIAL MANAGER DEFAULTS
+ // Credential manager is enabled by default so as to allow testing by app developers
+ private static final boolean DEFAULT_CREDENTIAL_MANAGER_ENABLED = true;
+ private static final boolean DEFAULT_CREDENTIAL_MANAGER_IGNORE_VIEWS = true;
+ private static final boolean DEFAULT_CREDENTIAL_MANAGER_SUPPRESS_FILL_DIALOG = false;
+ private static final boolean DEFAULT_CREDENTIAL_MANAGER_SUPPRESS_SAVE_DIALOG = false;
+ // END CREDENTIAL MANAGER DEFAULTS
+
+ private AutofillFeatureFlags() {};
+
+ /**
+ * Whether the fill dialog feature is enabled or not
+ *
+ * @hide
+ */
+ public static boolean isFillDialogEnabled() {
+ return DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_AUTOFILL,
+ DEVICE_CONFIG_AUTOFILL_DIALOG_ENABLED,
+ DEFAULT_HAS_FILL_DIALOG_UI_FEATURE);
+ }
+
+ /**
+ * Gets fill dialog enabled hints.
+ *
+ * @hide
+ */
+ public static String[] getFillDialogEnabledHints() {
+ final String dialogHints = DeviceConfig.getString(
+ DeviceConfig.NAMESPACE_AUTOFILL,
+ DEVICE_CONFIG_AUTOFILL_DIALOG_HINTS,
+ DEFAULT_FILL_DIALOG_ENABLED_HINTS);
+ if (TextUtils.isEmpty(dialogHints)) {
+ return new String[0];
+ }
+
+ return ArrayUtils.filter(dialogHints.split(DIALOG_HINTS_DELIMITER), String[]::new,
+ (str) -> !TextUtils.isEmpty(str));
+ }
+
+ /**
+ * Whether the Credential Manager feature is enabled or not
+ *
+ * @hide
+ */
+ public static boolean isCredentialManagerEnabled() {
+ return DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_AUTOFILL,
+ DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_ENABLED,
+ DEFAULT_CREDENTIAL_MANAGER_ENABLED);
+ }
+
+ /**
+ * Whether credential manager tagged views should be ignored for autofill structure.
+ *
+ * @hide
+ */
+ public static boolean shouldIgnoreCredentialViews() {
+ return isCredentialManagerEnabled()
+ && DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_AUTOFILL,
+ DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_IGNORE_VIEWS,
+ DEFAULT_CREDENTIAL_MANAGER_IGNORE_VIEWS);
+ }
+
+ /**
+ * Whether credential manager tagged views should not trigger fill dialog requests.
+ *
+ * @hide
+ */
+ public static boolean isFillDialogDisabledForCredentialManager() {
+ return isCredentialManagerEnabled()
+ && DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_AUTOFILL,
+ DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_SUPPRESS_FILL_DIALOG,
+ DEFAULT_CREDENTIAL_MANAGER_SUPPRESS_FILL_DIALOG);
+ }
+
+ /**
+ * Whether triggering fill request on unimportant view is enabled.
+ *
+ * @hide
+ */
+ public static boolean isTriggerFillRequestOnUnimportantViewEnabled() {
+ return DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_AUTOFILL,
+ DEVICE_CONFIG_TRIGGER_FILL_REQUEST_ON_UNIMPORTANT_VIEW, false);
+ }
+
+ /**
+ * Get the non-autofillable ime actions from flag. This will be used in filtering
+ * condition to trigger fill request.
+ *
+ * @hide
+ */
+ public static Set<String> getNonAutofillableImeActionIdSetFromFlag() {
+ final String mNonAutofillableImeActions = DeviceConfig.getString(
+ DeviceConfig.NAMESPACE_AUTOFILL, DEVICE_CONFIG_NON_AUTOFILLABLE_IME_ACTION_IDS, "");
+ return new ArraySet<>(Arrays.asList(mNonAutofillableImeActions.split(",")));
+ }
+
+ /**
+ * Get denylist string from flag
+ *
+ * @hide
+ */
+ public static String getDenylistStringFromFlag() {
+ return DeviceConfig.getString(
+ DeviceConfig.NAMESPACE_AUTOFILL,
+ DEVICE_CONFIG_PACKAGE_DENYLIST_FOR_UNIMPORTANT_VIEW, "");
+ }
+}
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index a92bc94..2ad01ed 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -60,7 +60,6 @@
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.SystemClock;
-import android.provider.DeviceConfig;
import android.service.autofill.AutofillService;
import android.service.autofill.FillCallback;
import android.service.autofill.FillEventHistory;
@@ -87,8 +86,13 @@
import android.view.accessibility.AccessibilityWindowInfo;
import android.view.inputmethod.InlineSuggestionsRequest;
import android.view.inputmethod.InputMethodManager;
+import android.widget.CheckBox;
+import android.widget.DatePicker;
import android.widget.EditText;
+import android.widget.RadioGroup;
+import android.widget.Spinner;
import android.widget.TextView;
+import android.widget.TimePicker;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.logging.MetricsLogger;
@@ -450,88 +454,6 @@
@Retention(RetentionPolicy.SOURCE)
public @interface SmartSuggestionMode {}
- /**
- * {@code DeviceConfig} property used to set which Smart Suggestion modes for Augmented Autofill
- * are available.
- *
- * @hide
- */
- @TestApi
- public static final String DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES =
- "smart_suggestion_supported_modes";
-
- /**
- * Sets how long (in ms) the augmented autofill service is bound while idle.
- *
- * <p>Use {@code 0} to keep it permanently bound.
- *
- * @hide
- */
- public static final String DEVICE_CONFIG_AUGMENTED_SERVICE_IDLE_UNBIND_TIMEOUT =
- "augmented_service_idle_unbind_timeout";
-
- /**
- * Sets how long (in ms) the augmented autofill service request is killed if not replied.
- *
- * @hide
- */
- public static final String DEVICE_CONFIG_AUGMENTED_SERVICE_REQUEST_TIMEOUT =
- "augmented_service_request_timeout";
-
- /**
- * Sets allowed list for the autofill compatibility mode.
- *
- * The list of packages is {@code ":"} colon delimited, and each entry has the name of the
- * package and an optional list of url bar resource ids (the list is delimited by
- * brackets&mdash{@code [} and {@code ]}&mdash and is also comma delimited).
- *
- * <p>For example, a list with 3 packages {@code p1}, {@code p2}, and {@code p3}, where
- * package {@code p1} have one id ({@code url_bar}, {@code p2} has none, and {@code p3 }
- * have 2 ids {@code url_foo} and {@code url_bas}) would be
- * {@code p1[url_bar]:p2:p3[url_foo,url_bas]}
- *
- * @hide
- */
- @TestApi
- public static final String DEVICE_CONFIG_AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES =
- "compat_mode_allowed_packages";
-
- /**
- * Sets the fill dialog feature enabled or not.
- *
- * @hide
- */
- @TestApi
- public static final String DEVICE_CONFIG_AUTOFILL_DIALOG_ENABLED =
- "autofill_dialog_enabled";
-
- /**
- * Sets the autofill hints allowed list for the fields that can trigger the fill dialog
- * feature at Activity starting.
- *
- * The list of autofill hints is {@code ":"} colon delimited.
- *
- * <p>For example, a list with 3 hints {@code password}, {@code phone}, and
- * {@code emailAddress}, would be {@code password:phone:emailAddress}
- *
- * Note: By default the password field is enabled even there is no password hint in the list
- *
- * @see View#setAutofillHints(String...)
- * @hide
- */
- public static final String DEVICE_CONFIG_AUTOFILL_DIALOG_HINTS =
- "autofill_dialog_hints";
-
- /**
- * Sets a value of delay time to show up the inline tooltip view.
- *
- * @hide
- */
- public static final String DEVICE_CONFIG_AUTOFILL_TOOLTIP_SHOW_UP_DELAY =
- "autofill_inline_tooltip_first_show_delay";
-
- private static final String DIALOG_HINTS_DELIMITER = ":";
-
/** @hide */
public static final int RESULT_OK = 0;
/** @hide */
@@ -634,9 +556,6 @@
*/
public static final int NO_SESSION = Integer.MAX_VALUE;
- private static final boolean HAS_FILL_DIALOG_UI_FEATURE_DEFAULT = false;
- private static final String FILL_DIALOG_ENABLED_DEFAULT_HINTS = "";
-
private final IAutoFillManager mService;
private final Object mLock = new Object();
@@ -743,6 +662,23 @@
private final boolean mIsFillDialogEnabled;
+ // Indicate whether trigger fill request on unimportant views is enabled
+ private boolean mIsTriggerFillRequestOnUnimportantViewEnabled = false;
+
+ // A set containing all non-autofillable ime actions passed by flag
+ private Set<String> mNonAutofillableImeActionIdSet = new ArraySet<>();
+
+ // If a package is fully denied, then all views that marked as not
+ // important for autofill will not trigger fill request
+ private boolean mIsPackageFullyDeniedForAutofillForUnimportantView = false;
+
+ // If a package is partially denied, autofill manager will check whether
+ // current activity is in deny set to decide whether to trigger fill request
+ private boolean mIsPackagePartiallyDeniedForAutofillForUnimportantView = false;
+
+ // A deny set read from device config
+ private Set<String> mDeniedActivitiySet = new ArraySet<>();
+
// Indicates whether called the showAutofillDialog() method.
private boolean mShowAutofillDialogCalled = false;
@@ -891,11 +827,8 @@
mOptions = context.getAutofillOptions();
mIsFillRequested = new AtomicBoolean(false);
- mIsFillDialogEnabled = DeviceConfig.getBoolean(
- DeviceConfig.NAMESPACE_AUTOFILL,
- DEVICE_CONFIG_AUTOFILL_DIALOG_ENABLED,
- HAS_FILL_DIALOG_UI_FEATURE_DEFAULT);
- mFillDialogEnabledHints = getFillDialogEnabledHints();
+ mIsFillDialogEnabled = AutofillFeatureFlags.isFillDialogEnabled();
+ mFillDialogEnabledHints = AutofillFeatureFlags.getFillDialogEnabledHints();
if (sDebug) {
Log.d(TAG, "Fill dialog is enabled:" + mIsFillDialogEnabled
+ ", hints=" + Arrays.toString(mFillDialogEnabledHints));
@@ -905,21 +838,133 @@
sDebug = (mOptions.loggingLevel & FLAG_ADD_CLIENT_DEBUG) != 0;
sVerbose = (mOptions.loggingLevel & FLAG_ADD_CLIENT_VERBOSE) != 0;
}
- }
- private String[] getFillDialogEnabledHints() {
- final String dialogHints = DeviceConfig.getString(
- DeviceConfig.NAMESPACE_AUTOFILL,
- DEVICE_CONFIG_AUTOFILL_DIALOG_HINTS,
- FILL_DIALOG_ENABLED_DEFAULT_HINTS);
- if (TextUtils.isEmpty(dialogHints)) {
- return new String[0];
+ mIsTriggerFillRequestOnUnimportantViewEnabled =
+ AutofillFeatureFlags.isTriggerFillRequestOnUnimportantViewEnabled();
+
+ mNonAutofillableImeActionIdSet =
+ AutofillFeatureFlags.getNonAutofillableImeActionIdSetFromFlag();
+
+ final String denyListString = AutofillFeatureFlags.getDenylistStringFromFlag();
+
+ final String packageName = mContext.getPackageName();
+
+ mIsPackageFullyDeniedForAutofillForUnimportantView =
+ isPackageFullyDeniedForAutofillForUnimportantView(denyListString, packageName);
+
+ mIsPackagePartiallyDeniedForAutofillForUnimportantView =
+ isPackagePartiallyDeniedForAutofillForUnimportantView(denyListString, packageName);
+
+ if (mIsPackagePartiallyDeniedForAutofillForUnimportantView) {
+ setDeniedActivitySetWithDenyList(denyListString, packageName);
}
-
- return ArrayUtils.filter(dialogHints.split(DIALOG_HINTS_DELIMITER), String[]::new,
- (str) -> !TextUtils.isEmpty(str));
}
+ private boolean isPackageFullyDeniedForAutofillForUnimportantView(
+ @NonNull String denyListString, @NonNull String packageName) {
+ // If "PackageName:;" is in the string, then it means the package name is in denylist
+ // and there are no activities specified under it. That means the package is fully
+ // denied for autofill
+ return denyListString.indexOf(packageName + ":;") != -1;
+ }
+
+ private boolean isPackagePartiallyDeniedForAutofillForUnimportantView(
+ @NonNull String denyListString, @NonNull String packageName) {
+ // This check happens after checking package is not fully denied. If "PackageName:" instead
+ // is in denylist, then it means there are specific activities to be denied. So the package
+ // is partially denied for autofill
+ return denyListString.indexOf(packageName + ":") != -1;
+ }
+
+ /**
+ * Get the denied activitiy names under specified package from denylist and set it in field
+ * mDeniedActivitiySet
+ *
+ * If using parameter as the example below, the denied activity set would be set to
+ * Set{Activity1,Activity2}.
+ *
+ * @param denyListString Denylist that is got from device config. For example,
+ * "Package1:Activity1,Activity2;Package2:;"
+ * @param packageName Specify to extract activities under which package.For example,
+ * "Package1:;"
+ */
+ private void setDeniedActivitySetWithDenyList(
+ @NonNull String denyListString, @NonNull String packageName) {
+ // 1. Get the index of where the Package name starts
+ final int packageInStringIndex = denyListString.indexOf(packageName + ":");
+
+ // 2. Get the ";" index after this index of package
+ final int firstNextSemicolonIndex = denyListString.indexOf(";", packageInStringIndex);
+
+ // 3. Get the activity names substring between the indexes
+ final int activityStringStartIndex = packageInStringIndex + packageName.length() + 1;
+ if (activityStringStartIndex < firstNextSemicolonIndex) {
+ Log.e(TAG, "Failed to get denied activity names from denylist because it's wrongly "
+ + "formatted");
+ }
+ final String activitySubstring =
+ denyListString.substring(activityStringStartIndex, firstNextSemicolonIndex);
+
+ // 4. Split the activity name substring
+ final String[] activityStringArray = activitySubstring.split(",");
+
+ // 5. Set the denied activity set
+ mDeniedActivitiySet = new ArraySet<>(Arrays.asList(activityStringArray));
+
+ return;
+ }
+
+ /**
+ * Check whether autofill is denied for current activity or package. Used when a view is marked
+ * as not important for autofill, if current activity or package is denied, then the view won't
+ * trigger fill request.
+ *
+ * @hide
+ */
+ public final boolean isActivityDeniedForAutofillForUnimportantView() {
+ if (mIsPackageFullyDeniedForAutofillForUnimportantView) {
+ return true;
+ }
+ if (mIsPackagePartiallyDeniedForAutofillForUnimportantView) {
+ final AutofillClient client = getClient();
+ if (client == null) {
+ return false;
+ }
+ final ComponentName clientActivity = client.autofillClientGetComponentName();
+ if (mDeniedActivitiySet.contains(clientActivity.flattenToShortString())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Check whether view matches autofill-able heuristics
+ *
+ * @hide
+ */
+ public final boolean isMatchingAutofillableHeuristics(@NonNull View view) {
+ if (!mIsTriggerFillRequestOnUnimportantViewEnabled) {
+ return false;
+ }
+ if (view instanceof EditText) {
+ final int actionId = ((EditText) view).getImeOptions();
+ if (mNonAutofillableImeActionIdSet.contains(String.valueOf(actionId))) {
+ return false;
+ }
+ return true;
+ }
+ if (view instanceof CheckBox
+ || view instanceof Spinner
+ || view instanceof DatePicker
+ || view instanceof TimePicker
+ || view instanceof RadioGroup) {
+ return true;
+ }
+ return false;
+ }
+
+
/**
* @hide
*/
@@ -1190,16 +1235,28 @@
}
/**
- * The {@link #DEVICE_CONFIG_AUTOFILL_DIALOG_ENABLED} is {@code true} or the view have
- * the allowed autofill hints, performs a fill request to know there is any field supported
- * fill dialog.
+ * The {@link AutofillFeatureFlags#DEVICE_CONFIG_AUTOFILL_DIALOG_ENABLED} is {@code true} or
+ * the view have the allowed autofill hints, performs a fill request to know there is any field
+ * supported fill dialog.
*
* @hide
*/
public void notifyViewEnteredForFillDialog(View v) {
+ if (sDebug) {
+ Log.d(TAG, "notifyViewEnteredForFillDialog:" + v.getAutofillId());
+ }
if (!hasAutofillFeature()) {
return;
}
+ if (AutofillFeatureFlags.isFillDialogDisabledForCredentialManager()
+ && v.isCredential()) {
+ if (sDebug) {
+ Log.d(TAG, "Ignoring Fill Dialog request since important for credMan:"
+ + v.getAutofillId().toString());
+ }
+ return;
+ }
+
synchronized (mLock) {
if (mTrackedViews != null) {
// To support the fill dialog can show for the autofillable Views in
@@ -1227,8 +1284,8 @@
synchronized (mLock) {
// To match the id of the IME served view, used AutofillId.NO_AUTOFILL_ID on prefill
// request, because IME will reset the id of IME served view to 0 when activity
- // start and does not focus on any view. If the id of the prefill request is
- // not match to the IME served view's, Autofill will be blocking to wait inline
+ // start and does not focus on any view. If the id of the prefill request does
+ // not match the IME served view's, Autofill will be blocking to wait inline
// request from the IME.
notifyViewEnteredLocked(/* view= */ null, AutofillId.NO_AUTOFILL_ID,
/* bounds= */ null, /* value= */ null, flags);
@@ -4075,6 +4132,7 @@
}
}
+ @Override
public void notifyFillDialogTriggerIds(List<AutofillId> ids) {
final AutofillManager afm = mAfm.get();
if (afm != null) {
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index d067d4b..497f066 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -66,8 +66,7 @@
import java.util.function.Consumer;
/**
- * <p>The {@link ContentCaptureManager} provides additional ways for for apps to
- * integrate with the content capture subsystem.
+ * <p>Provides additional ways for apps to integrate with the content capture subsystem.
*
* <p>Content capture provides real-time, continuous capture of application activity, display and
* events to an intelligence service that is provided by the Android system. The intelligence
diff --git a/core/java/android/view/inputmethod/HandwritingGesture.java b/core/java/android/view/inputmethod/HandwritingGesture.java
index 2516269..1f4a7af 100644
--- a/core/java/android/view/inputmethod/HandwritingGesture.java
+++ b/core/java/android/view/inputmethod/HandwritingGesture.java
@@ -17,10 +17,13 @@
package android.view.inputmethod;
import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.graphics.RectF;
import android.inputmethodservice.InputMethodService;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.view.MotionEvent;
import java.lang.annotation.Retention;
@@ -82,38 +85,60 @@
@IntDef({GRANULARITY_CHARACTER, GRANULARITY_WORD})
@interface Granularity {}
- /** Undefined gesture type. */
+ /**
+ * Undefined gesture type.
+ * @hide
+ */
+ @TestApi
public static final int GESTURE_TYPE_NONE = 0x0000;
/**
* Gesture of type {@link SelectGesture} to select an area of text.
+ * @hide
*/
+ @TestApi
public static final int GESTURE_TYPE_SELECT = 0x0001;
/**
* Gesture of type {@link InsertGesture} to insert text at a designated point.
+ * @hide
*/
+ @TestApi
public static final int GESTURE_TYPE_INSERT = 1 << 1;
/**
* Gesture of type {@link DeleteGesture} to delete an area of text.
+ * @hide
*/
+ @TestApi
public static final int GESTURE_TYPE_DELETE = 1 << 2;
- /** Gesture of type {@link RemoveSpaceGesture} to remove whitespace from text. */
+ /**
+ * Gesture of type {@link RemoveSpaceGesture} to remove whitespace from text.
+ * @hide
+ */
+ @TestApi
public static final int GESTURE_TYPE_REMOVE_SPACE = 1 << 3;
- /** Gesture of type {@link JoinOrSplitGesture} to join or split text. */
+ /**
+ * Gesture of type {@link JoinOrSplitGesture} to join or split text.
+ * @hide
+ */
+ @TestApi
public static final int GESTURE_TYPE_JOIN_OR_SPLIT = 1 << 4;
/**
* Gesture of type {@link SelectRangeGesture} to select range of text.
+ * @hide
*/
+ @TestApi
public static final int GESTURE_TYPE_SELECT_RANGE = 1 << 5;
/**
* Gesture of type {@link DeleteRangeGesture} to delete range of text.
+ * @hide
*/
+ @TestApi
public static final int GESTURE_TYPE_DELETE_RANGE = 1 << 6;
/**
@@ -176,4 +201,56 @@
public final String getFallbackText() {
return mFallbackText;
}
+
+ /**
+ * Dump data into a byte array so that you can pass the data across process boundary.
+ *
+ * @return byte array data.
+ * @see #fromByteArray(byte[])
+ * @hide
+ */
+ @TestApi
+ @NonNull
+ public final byte[] toByteArray() {
+ if (!(this instanceof Parcelable)) {
+ throw new UnsupportedOperationException(getClass() + " is not Parcelable");
+ }
+ final Parcelable self = (Parcelable) this;
+ if ((self.describeContents() & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0) {
+ throw new UnsupportedOperationException("Gesture that contains FD is not supported");
+ }
+ Parcel parcel = null;
+ try {
+ parcel = Parcel.obtain();
+ ParcelableHandwritingGesture.of(this).writeToParcel(parcel, 0);
+ return parcel.marshall();
+ } finally {
+ if (parcel != null) {
+ parcel.recycle();
+ }
+ }
+ }
+
+ /**
+ * Create a new instance from byte array obtained from {@link #toByteArray()}.
+ *
+ * @param buffer byte array obtained from {@link #toByteArray()}
+ * @return A new instance of {@link HandwritingGesture} subclass.
+ * @hide
+ */
+ @TestApi
+ @NonNull
+ public static HandwritingGesture fromByteArray(@NonNull byte[] buffer) {
+ Parcel parcel = null;
+ try {
+ parcel = Parcel.obtain();
+ parcel.unmarshall(buffer, 0, buffer.length);
+ parcel.setDataPosition(0);
+ return ParcelableHandwritingGesture.CREATOR.createFromParcel(parcel).get();
+ } finally {
+ if (parcel != null) {
+ parcel.recycle();
+ }
+ }
+ }
}
diff --git a/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java b/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java
index f08f61f..96602619 100644
--- a/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java
+++ b/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java
@@ -215,6 +215,21 @@
}
@AnyThread
+ @Nullable
+ @RequiresPermission(value = Manifest.permission.INTERACT_ACROSS_USERS_FULL, conditional = true)
+ static InputMethodInfo getCurrentInputMethodInfoAsUser(@UserIdInt int userId) {
+ final IInputMethodManager service = getService();
+ if (service == null) {
+ return null;
+ }
+ try {
+ return service.getCurrentInputMethodInfoAsUser(userId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ @AnyThread
@NonNull
@RequiresPermission(value = Manifest.permission.INTERACT_ACROSS_USERS_FULL, conditional = true)
static List<InputMethodInfo> getInputMethodList(@UserIdInt int userId,
diff --git a/core/java/android/view/inputmethod/ImeTracker.java b/core/java/android/view/inputmethod/ImeTracker.java
index 3b6ec80..a07dedc 100644
--- a/core/java/android/view/inputmethod/ImeTracker.java
+++ b/core/java/android/view/inputmethod/ImeTracker.java
@@ -16,24 +16,36 @@
package android.view.inputmethod;
+import static com.android.internal.inputmethod.InputMethodDebug.softInputDisplayReasonToString;
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_IME_INSETS_ANIMATION;
+import static com.android.internal.util.LatencyTracker.ACTION_REQUEST_IME_HIDDEN;
+import static com.android.internal.util.LatencyTracker.ACTION_REQUEST_IME_SHOWN;
+
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityThread;
+import android.content.Context;
import android.os.Binder;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemProperties;
import android.util.Log;
+import android.view.InsetsController.AnimationType;
+import android.view.SurfaceControl;
import com.android.internal.inputmethod.InputMethodDebug;
import com.android.internal.inputmethod.SoftInputShowHideReason;
+import com.android.internal.jank.InteractionJankMonitor;
+import com.android.internal.jank.InteractionJankMonitor.Configuration;
+import com.android.internal.util.LatencyTracker;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Field;
import java.util.Arrays;
+import java.util.Locale;
import java.util.Map;
import java.util.Random;
import java.util.stream.Collectors;
@@ -385,15 +397,35 @@
void onHidden(@Nullable Token token);
/**
- * Get the singleton instance of this class.
+ * Get the singleton request tracker instance.
*
- * @return the singleton instance of this class
+ * @return the singleton request tracker instance
*/
@NonNull
- static ImeTracker get() {
+ static ImeTracker forLogging() {
return LOGGER;
}
+ /**
+ * Get the singleton jank tracker instance.
+ *
+ * @return the singleton jank tracker instance
+ */
+ @NonNull
+ static ImeJankTracker forJank() {
+ return JANK_TRACKER;
+ }
+
+ /**
+ * Get the singleton latency tracker instance.
+ *
+ * @return the singleton latency tracker instance
+ */
+ @NonNull
+ static ImeLatencyTracker forLatency() {
+ return LATENCY_TRACKER;
+ }
+
/** The singleton IME tracker instance. */
@NonNull
ImeTracker LOGGER = new ImeTracker() {
@@ -489,6 +521,12 @@
}
};
+ /** The singleton IME tracker instance for instrumenting jank metrics. */
+ ImeJankTracker JANK_TRACKER = new ImeJankTracker();
+
+ /** The singleton IME tracker instance for instrumenting latency metrics. */
+ ImeLatencyTracker LATENCY_TRACKER = new ImeLatencyTracker();
+
/** A token that tracks the progress of an IME request. */
class Token implements Parcelable {
@@ -592,4 +630,153 @@
}
}
}
+
+ /**
+ * Context related to {@link InteractionJankMonitor}.
+ */
+ interface InputMethodJankContext {
+ /**
+ * @return a context associated with a display
+ */
+ Context getDisplayContext();
+
+ /**
+ * @return a SurfaceControl is going to be monitored
+ */
+ SurfaceControl getTargetSurfaceControl();
+
+ /**
+ * @return the package name of the host
+ */
+ String getHostPackageName();
+ }
+
+ /**
+ * Context related to {@link LatencyTracker}.
+ */
+ interface InputMethodLatencyContext {
+ /**
+ * @return a context associated with current application
+ */
+ Context getAppContext();
+ }
+
+ /**
+ * A tracker instance which is in charge of communicating with {@link InteractionJankMonitor}.
+ */
+ final class ImeJankTracker {
+
+ private ImeJankTracker() {
+ }
+
+ /**
+ * Called when the animation, which is going to be monitored, starts.
+ *
+ * @param jankContext context which is needed by {@link InteractionJankMonitor}
+ * @param animType {@link AnimationType}
+ * @param useSeparatedThread {@code true} if the animation is handled by the app,
+ * {@code false} if the animation will be scheduled on the
+ * {@link android.view.InsetsAnimationThread}
+ */
+ public void onRequestAnimation(@NonNull InputMethodJankContext jankContext,
+ @AnimationType int animType, boolean useSeparatedThread) {
+ if (jankContext.getDisplayContext() == null
+ || jankContext.getTargetSurfaceControl() == null) {
+ return;
+ }
+ final Configuration.Builder builder = Configuration.Builder.withSurface(
+ CUJ_IME_INSETS_ANIMATION,
+ jankContext.getDisplayContext(),
+ jankContext.getTargetSurfaceControl())
+ .setTag(String.format(Locale.US, "%d@%d@%s", animType,
+ useSeparatedThread ? 0 : 1, jankContext.getHostPackageName()));
+ InteractionJankMonitor.getInstance().begin(builder);
+ }
+
+ /**
+ * Called when the animation, which is going to be monitored, cancels.
+ */
+ public void onCancelAnimation() {
+ InteractionJankMonitor.getInstance().cancel(CUJ_IME_INSETS_ANIMATION);
+ }
+
+ /**
+ * Called when the animation, which is going to be monitored, ends.
+ */
+ public void onFinishAnimation() {
+ InteractionJankMonitor.getInstance().end(CUJ_IME_INSETS_ANIMATION);
+ }
+ }
+
+ /**
+ * A tracker instance which is in charge of communicating with {@link LatencyTracker}.
+ */
+ final class ImeLatencyTracker {
+
+ private ImeLatencyTracker() {
+ }
+
+ private boolean shouldMonitorLatency(@SoftInputShowHideReason int reason) {
+ return reason == SoftInputShowHideReason.SHOW_SOFT_INPUT
+ || reason == SoftInputShowHideReason.HIDE_SOFT_INPUT
+ || reason == SoftInputShowHideReason.SHOW_SOFT_INPUT_BY_INSETS_API
+ || reason == SoftInputShowHideReason.HIDE_SOFT_INPUT_BY_INSETS_API
+ || reason == SoftInputShowHideReason.SHOW_SOFT_INPUT_FROM_IME
+ || reason == SoftInputShowHideReason.HIDE_SOFT_INPUT_FROM_IME;
+ }
+
+ public void onRequestShow(@Nullable Token token, @Origin int origin,
+ @SoftInputShowHideReason int reason,
+ @NonNull InputMethodLatencyContext latencyContext) {
+ if (!shouldMonitorLatency(reason)) return;
+ LatencyTracker.getInstance(latencyContext.getAppContext())
+ .onActionStart(
+ ACTION_REQUEST_IME_SHOWN,
+ softInputDisplayReasonToString(reason));
+ }
+
+ public void onRequestHide(@Nullable Token token, @Origin int origin,
+ @SoftInputShowHideReason int reason,
+ @NonNull InputMethodLatencyContext latencyContext) {
+ if (!shouldMonitorLatency(reason)) return;
+ LatencyTracker.getInstance(latencyContext.getAppContext())
+ .onActionStart(
+ ACTION_REQUEST_IME_HIDDEN,
+ softInputDisplayReasonToString(reason));
+ }
+
+ public void onShowFailed(@Nullable Token token, @Phase int phase,
+ @NonNull InputMethodLatencyContext latencyContext) {
+ onShowCancelled(token, phase, latencyContext);
+ }
+
+ public void onHideFailed(@Nullable Token token, @Phase int phase,
+ @NonNull InputMethodLatencyContext latencyContext) {
+ onHideCancelled(token, phase, latencyContext);
+ }
+
+ public void onShowCancelled(@Nullable Token token, @Phase int phase,
+ @NonNull InputMethodLatencyContext latencyContext) {
+ LatencyTracker.getInstance(latencyContext.getAppContext())
+ .onActionCancel(ACTION_REQUEST_IME_SHOWN);
+ }
+
+ public void onHideCancelled(@Nullable Token token, @Phase int phase,
+ @NonNull InputMethodLatencyContext latencyContext) {
+ LatencyTracker.getInstance(latencyContext.getAppContext())
+ .onActionCancel(ACTION_REQUEST_IME_HIDDEN);
+ }
+
+ public void onShown(@Nullable Token token,
+ @NonNull InputMethodLatencyContext latencyContext) {
+ LatencyTracker.getInstance(latencyContext.getAppContext())
+ .onActionEnd(ACTION_REQUEST_IME_SHOWN);
+ }
+
+ public void onHidden(@Nullable Token token,
+ @NonNull InputMethodLatencyContext latencyContext) {
+ LatencyTracker.getInstance(latencyContext.getAppContext())
+ .onActionEnd(ACTION_REQUEST_IME_HIDDEN);
+ }
+ }
}
diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java
index 9b519c3..6872536 100644
--- a/core/java/android/view/inputmethod/InputConnection.java
+++ b/core/java/android/view/inputmethod/InputConnection.java
@@ -1262,13 +1262,13 @@
/**
* Called by input method to request the {@link TextBoundsInfo} for a range of text which is
- * covered by or in vicinity of the given {@code RectF}. It can be used as a supplementary
+ * covered by or in vicinity of the given {@code bounds}. It can be used as a supplementary
* method to implement the handwriting gesture API -
* {@link #performHandwritingGesture(HandwritingGesture, Executor, IntConsumer)}.
*
* <p><strong>Editor authors</strong>: It's preferred that the editor returns a
* {@link TextBoundsInfo} of all the text lines whose bounds intersect with the given
- * {@code rectF}.
+ * {@code bounds}.
* </p>
*
* <p><strong>IME authors</strong>: This method is expensive when the text is long. Please
@@ -1276,7 +1276,7 @@
* consuming. It's preferable to only request text bounds in smaller areas.
* </p>
*
- * @param rectF the interested area where the text bounds are requested, in the screen
+ * @param bounds the interested area where the text bounds are requested, in the screen
* coordinates.
* @param executor the executor to run the callback.
* @param consumer the callback invoked by editor to return the result. It must return a
@@ -1286,7 +1286,7 @@
* @see android.view.inputmethod.TextBoundsInfoResult
*/
default void requestTextBoundsInfo(
- @NonNull RectF rectF, @NonNull @CallbackExecutor Executor executor,
+ @NonNull RectF bounds, @NonNull @CallbackExecutor Executor executor,
@NonNull Consumer<TextBoundsInfoResult> consumer) {
Objects.requireNonNull(executor);
Objects.requireNonNull(consumer);
diff --git a/core/java/android/view/inputmethod/InputConnectionWrapper.java b/core/java/android/view/inputmethod/InputConnectionWrapper.java
index 4befd6f..5e323fa 100644
--- a/core/java/android/view/inputmethod/InputConnectionWrapper.java
+++ b/core/java/android/view/inputmethod/InputConnectionWrapper.java
@@ -362,9 +362,9 @@
*/
@Override
public void requestTextBoundsInfo(
- @NonNull RectF rectF, @NonNull @CallbackExecutor Executor executor,
+ @NonNull RectF bounds, @NonNull @CallbackExecutor Executor executor,
@NonNull Consumer<TextBoundsInfoResult> consumer) {
- mTarget.requestTextBoundsInfo(rectF, executor, consumer);
+ mTarget.requestTextBoundsInfo(bounds, executor, consumer);
}
/**
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index b7da732..229cc02 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -339,6 +339,28 @@
mIsVrOnly = isVrOnly;
}
+ /**
+ * @hide
+ */
+ public InputMethodInfo(InputMethodInfo source) {
+ mId = source.mId;
+ mSettingsActivityName = source.mSettingsActivityName;
+ mIsDefaultResId = source.mIsDefaultResId;
+ mIsAuxIme = source.mIsAuxIme;
+ mSupportsSwitchingToNextInputMethod = source.mSupportsSwitchingToNextInputMethod;
+ mInlineSuggestionsEnabled = source.mInlineSuggestionsEnabled;
+ mSupportsInlineSuggestionsWithTouchExploration =
+ source.mSupportsInlineSuggestionsWithTouchExploration;
+ mSuppressesSpellChecker = source.mSuppressesSpellChecker;
+ mShowInInputMethodPicker = source.mShowInInputMethodPicker;
+ mIsVrOnly = source.mIsVrOnly;
+ mService = source.mService;
+ mSubtypes = source.mSubtypes;
+ mHandledConfigChanges = source.mHandledConfigChanges;
+ mSupportsStylusHandwriting = source.mSupportsStylusHandwriting;
+ mForceDefault = source.mForceDefault;
+ }
+
InputMethodInfo(Parcel source) {
mId = source.readString();
mSettingsActivityName = source.readString();
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index c1b6cda..642182b 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -43,6 +43,8 @@
import android.annotation.Nullable;
import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
import android.annotation.UiThread;
@@ -1598,6 +1600,37 @@
}
/**
+ * Returns the {@link InputMethodInfo} of the currently selected input method (for the process's
+ * user).
+ *
+ * <p>On multi user environment, this API returns a result for the calling process user.</p>
+ */
+ @Nullable
+ public InputMethodInfo getCurrentInputMethodInfo() {
+ // We intentionally do not use UserHandle.getCallingUserId() here because for system
+ // services InputMethodManagerInternal.getCurrentInputMethodInfoForUser() should be used
+ // instead.
+ return IInputMethodManagerGlobalInvoker.getCurrentInputMethodInfoAsUser(
+ UserHandle.myUserId());
+ }
+
+ /**
+ * Returns the {@link InputMethodInfo} for currently selected input method for the given user.
+ *
+ * @param user user to query.
+ * @hide
+ */
+ @RequiresPermission(value = Manifest.permission.INTERACT_ACROSS_USERS_FULL)
+ @Nullable
+ @SystemApi
+ @SuppressLint("UserHandle")
+ public InputMethodInfo getCurrentInputMethodInfoAsUser(@NonNull UserHandle user) {
+ Objects.requireNonNull(user);
+ return IInputMethodManagerGlobalInvoker.getCurrentInputMethodInfoAsUser(
+ user.getIdentifier());
+ }
+
+ /**
* Returns the list of enabled input methods.
*
* <p>On multi user environment, this API returns a result for the calling process user.</p>
@@ -2012,10 +2045,11 @@
private boolean showSoftInput(View view, @Nullable ImeTracker.Token statsToken, int flags,
ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
if (statsToken == null) {
- statsToken = ImeTracker.get().onRequestShow(null /* component */,
+ statsToken = ImeTracker.forLogging().onRequestShow(null /* component */,
Process.myUid(), ImeTracker.ORIGIN_CLIENT_SHOW_SOFT_INPUT, reason);
}
-
+ ImeTracker.forLatency().onRequestShow(statsToken, ImeTracker.ORIGIN_CLIENT_SHOW_SOFT_INPUT,
+ reason, ActivityThread::currentApplication);
ImeTracing.getInstance().triggerClientDump("InputMethodManager#showSoftInput", this,
null /* icProto */);
// Re-dispatch if there is a context mismatch.
@@ -2027,12 +2061,15 @@
checkFocus();
synchronized (mH) {
if (!hasServedByInputMethodLocked(view)) {
- ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
+ ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
+ ImeTracker.forLatency().onShowFailed(
+ statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED,
+ ActivityThread::currentApplication);
Log.w(TAG, "Ignoring showSoftInput() as view=" + view + " is not served.");
return false;
}
- ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
+ ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
// Makes sure to call ImeInsetsSourceConsumer#onShowRequested on the UI thread.
// TODO(b/229426865): call WindowInsetsController#show instead.
@@ -2062,20 +2099,20 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768499)
public void showSoftInputUnchecked(int flags, ResultReceiver resultReceiver) {
synchronized (mH) {
- final ImeTracker.Token statsToken = ImeTracker.get().onRequestShow(null /* component */,
- Process.myUid(), ImeTracker.ORIGIN_CLIENT_SHOW_SOFT_INPUT,
+ final ImeTracker.Token statsToken = ImeTracker.forLogging().onRequestShow(
+ null /* component */, Process.myUid(), ImeTracker.ORIGIN_CLIENT_SHOW_SOFT_INPUT,
SoftInputShowHideReason.SHOW_SOFT_INPUT);
Log.w(TAG, "showSoftInputUnchecked() is a hidden method, which will be"
+ " removed soon. If you are using androidx.appcompat.widget.SearchView,"
+ " please update to version 26.0 or newer version.");
if (mCurRootView == null || mCurRootView.getView() == null) {
- ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
+ ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
Log.w(TAG, "No current root view, ignoring showSoftInputUnchecked()");
return;
}
- ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
+ ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
// Makes sure to call ImeInsetsSourceConsumer#onShowRequested on the UI thread.
// TODO(b/229426865): call WindowInsetsController#show instead.
@@ -2153,20 +2190,24 @@
private boolean hideSoftInputFromWindow(IBinder windowToken, int flags,
ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
- final ImeTracker.Token statsToken = ImeTracker.get().onRequestHide(null /* component */,
- Process.myUid(), ImeTracker.ORIGIN_CLIENT_HIDE_SOFT_INPUT, reason);
-
+ final ImeTracker.Token statsToken = ImeTracker.forLogging().onRequestHide(
+ null /* component */, Process.myUid(),
+ ImeTracker.ORIGIN_CLIENT_HIDE_SOFT_INPUT, reason);
+ ImeTracker.forLatency().onRequestHide(statsToken, ImeTracker.ORIGIN_CLIENT_HIDE_SOFT_INPUT,
+ reason, ActivityThread::currentApplication);
ImeTracing.getInstance().triggerClientDump("InputMethodManager#hideSoftInputFromWindow",
this, null /* icProto */);
checkFocus();
synchronized (mH) {
final View servedView = getServedViewLocked();
if (servedView == null || servedView.getWindowToken() != windowToken) {
- ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
+ ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
+ ImeTracker.forLatency().onHideFailed(statsToken,
+ ImeTracker.PHASE_CLIENT_VIEW_SERVED, ActivityThread::currentApplication);
return false;
}
- ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
+ ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
return IInputMethodManagerGlobalInvoker.hideSoftInput(mClient, windowToken, statsToken,
flags, resultReceiver, reason);
@@ -2802,18 +2843,22 @@
@UnsupportedAppUsage
void closeCurrentInput() {
- final ImeTracker.Token statsToken = ImeTracker.get().onRequestHide(null /* component */,
- Process.myUid(), ImeTracker.ORIGIN_CLIENT_HIDE_SOFT_INPUT,
+ final ImeTracker.Token statsToken = ImeTracker.forLogging().onRequestHide(
+ null /* component */, Process.myUid(), ImeTracker.ORIGIN_CLIENT_HIDE_SOFT_INPUT,
SoftInputShowHideReason.HIDE_SOFT_INPUT);
+ ImeTracker.forLatency().onRequestHide(statsToken, ImeTracker.ORIGIN_CLIENT_HIDE_SOFT_INPUT,
+ SoftInputShowHideReason.HIDE_SOFT_INPUT, ActivityThread::currentApplication);
synchronized (mH) {
if (mCurRootView == null || mCurRootView.getView() == null) {
- ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
+ ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
+ ImeTracker.forLatency().onHideFailed(statsToken,
+ ImeTracker.PHASE_CLIENT_VIEW_SERVED, ActivityThread::currentApplication);
Log.w(TAG, "No current root view, ignoring closeCurrentInput()");
return;
}
- ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
+ ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
IInputMethodManagerGlobalInvoker.hideSoftInput(
mClient,
@@ -2872,11 +2917,13 @@
synchronized (mH) {
final View servedView = getServedViewLocked();
if (servedView == null || servedView.getWindowToken() != windowToken) {
- ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_CLIENT_REQUEST_IME_SHOW);
+ ImeTracker.forLogging().onFailed(statsToken,
+ ImeTracker.PHASE_CLIENT_REQUEST_IME_SHOW);
return false;
}
- ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_REQUEST_IME_SHOW);
+ ImeTracker.forLogging().onProgress(statsToken,
+ ImeTracker.PHASE_CLIENT_REQUEST_IME_SHOW);
showSoftInput(servedView, statsToken, 0 /* flags */, null /* resultReceiver */,
SoftInputShowHideReason.SHOW_SOFT_INPUT_BY_INSETS_API);
@@ -2894,21 +2941,25 @@
*/
public void notifyImeHidden(IBinder windowToken, @Nullable ImeTracker.Token statsToken) {
if (statsToken == null) {
- statsToken = ImeTracker.get().onRequestHide(null /* component */,
+ statsToken = ImeTracker.forLogging().onRequestHide(null /* component */,
Process.myUid(), ImeTracker.ORIGIN_CLIENT_HIDE_SOFT_INPUT,
SoftInputShowHideReason.HIDE_SOFT_INPUT_BY_INSETS_API);
}
-
+ ImeTracker.forLatency().onRequestHide(statsToken, ImeTracker.ORIGIN_CLIENT_HIDE_SOFT_INPUT,
+ SoftInputShowHideReason.HIDE_SOFT_INPUT_BY_INSETS_API,
+ ActivityThread::currentApplication);
ImeTracing.getInstance().triggerClientDump("InputMethodManager#notifyImeHidden", this,
null /* icProto */);
synchronized (mH) {
if (!isImeSessionAvailableLocked() || mCurRootView == null
|| mCurRootView.getWindowToken() != windowToken) {
- ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
+ ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
+ ImeTracker.forLatency().onHideFailed(statsToken,
+ ImeTracker.PHASE_CLIENT_VIEW_SERVED, ActivityThread::currentApplication);
return;
}
- ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
+ ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
IInputMethodManagerGlobalInvoker.hideSoftInput(mClient, windowToken, statsToken,
0 /* flags */, null /* resultReceiver */,
diff --git a/core/java/android/view/inputmethod/RemoteInputConnectionImpl.java b/core/java/android/view/inputmethod/RemoteInputConnectionImpl.java
index 7525d72..6f8b422 100644
--- a/core/java/android/view/inputmethod/RemoteInputConnectionImpl.java
+++ b/core/java/android/view/inputmethod/RemoteInputConnectionImpl.java
@@ -1106,7 +1106,7 @@
@Dispatching(cancellable = true)
@Override
public void requestTextBoundsInfo(
- InputConnectionCommandHeader header, RectF rectF,
+ InputConnectionCommandHeader header, RectF bounds,
@NonNull ResultReceiver resultReceiver) {
dispatchWithTracing("requestTextBoundsInfo", () -> {
if (header.mSessionId != mCurrentSessionId.get()) {
@@ -1121,7 +1121,7 @@
}
ic.requestTextBoundsInfo(
- rectF,
+ bounds,
Runnable::run,
(textBoundsInfoResult) -> {
final int resultCode = textBoundsInfoResult.getResultCode();
diff --git a/core/java/android/view/inputmethod/TextBoundsInfo.java b/core/java/android/view/inputmethod/TextBoundsInfo.java
index dd05543..d42d94e 100644
--- a/core/java/android/view/inputmethod/TextBoundsInfo.java
+++ b/core/java/android/view/inputmethod/TextBoundsInfo.java
@@ -43,8 +43,8 @@
* The text bounds information of a slice of text in the editor.
*
* <p> This class provides IME the layout information of the text within the range from
- * {@link #getStart()} to {@link #getEnd()}. It's intended to be used by IME as a supplementary API
- * to support handwriting gestures.
+ * {@link #getStartIndex()} to {@link #getEndIndex()}. It's intended to be used by IME as a
+ * supplementary API to support handwriting gestures.
* </p>
*/
public final class TextBoundsInfo implements Parcelable {
@@ -168,16 +168,13 @@
private final SegmentFinder mGraphemeSegmentFinder;
/**
- * Returns a new instance of {@link android.graphics.Matrix} that indicates the transformation
+ * Set the given {@link android.graphics.Matrix} to be the transformation
* matrix that is to be applied other positional data in this class.
- *
- * @return a new instance (copy) of the transformation matrix.
*/
@NonNull
- public Matrix getMatrix() {
- final Matrix matrix = new Matrix();
+ public void getMatrix(@NonNull Matrix matrix) {
+ Objects.requireNonNull(matrix);
matrix.setValues(mMatrixValues);
- return matrix;
}
/**
@@ -186,7 +183,7 @@
*
* @see Builder#setStartAndEnd(int, int)
*/
- public int getStart() {
+ public int getStartIndex() {
return mStart;
}
@@ -196,28 +193,28 @@
*
* @see Builder#setStartAndEnd(int, int)
*/
- public int getEnd() {
+ public int getEndIndex() {
return mEnd;
}
/**
- * Return the bounds of the character at the given {@code index}, in the coordinates of the
- * editor.
+ * Set the bounds of the character at the given {@code index} to the given {@link RectF}, in
+ * the coordinates of the editor.
*
* @param index the index of the queried character.
- * @return the bounding box of the queried character.
+ * @param bounds the {@link RectF} used to receive the result.
*
* @throws IndexOutOfBoundsException if the given {@code index} is out of the range from
* the {@code start} to the {@code end}.
*/
@NonNull
- public RectF getCharacterBounds(int index) {
+ public void getCharacterBounds(int index, @NonNull RectF bounds) {
if (index < mStart || index >= mEnd) {
throw new IndexOutOfBoundsException("Index is out of the bounds of "
+ "[" + mStart + ", " + mEnd + ").");
}
final int offset = 4 * (index - mStart);
- return new RectF(mCharacterBounds[offset], mCharacterBounds[offset + 1],
+ bounds.set(mCharacterBounds[offset], mCharacterBounds[offset + 1],
mCharacterBounds[offset + 2], mCharacterBounds[offset + 3]);
}
@@ -333,6 +330,16 @@
* won't check the text in the ranges of [5, 7) and [12, 15).
* </p>
*
+ * <p> Under the following conditions, this method will return -1 indicating that no valid
+ * character is found:
+ * <ul>
+ * <li> The given {@code y} coordinate is above the first line or below the last line (the
+ * first line or the last line is identified by the {@link SegmentFinder} returned from
+ * {@link #getLineSegmentFinder()}). </li>
+ * <li> There is no character in this {@link TextBoundsInfo}. </li>
+ * </ul>
+ * </p>
+ *
* @param x the x coordinates of the interested location, in the editor's coordinates.
* @param y the y coordinates of the interested location, in the editor's coordinates.
* @return the index of the character whose position is closest to the given location. It will
@@ -990,8 +997,8 @@
public static final class Builder {
private final float[] mMatrixValues = new float[9];
private boolean mMatrixInitialized;
- private int mStart;
- private int mEnd;
+ private int mStart = -1;
+ private int mEnd = -1;
private float[] mCharacterBounds;
private int[] mCharacterFlags;
private int[] mCharacterBidiLevels;
@@ -999,6 +1006,17 @@
private SegmentFinder mWordSegmentFinder;
private SegmentFinder mGraphemeSegmentFinder;
+ /**
+ * Create a builder for {@link TextBoundsInfo}.
+ * @param start the start index of the {@link TextBoundsInfo}, inclusive.
+ * @param end the end index of the {@link TextBoundsInfo}, exclusive.
+ * @throws IllegalArgumentException if the given {@code start} or {@code end} is negative,
+ * or {@code end} is smaller than the {@code start}.
+ */
+ public Builder(int start, int end) {
+ setStartAndEnd(start, end);
+ }
+
/** Clear all the parameters set on this {@link Builder} to reuse it. */
@NonNull
public Builder clear() {
@@ -1152,7 +1170,7 @@
*
* @see #getGraphemeSegmentFinder()
* @see SegmentFinder
- * @see SegmentFinder.DefaultSegmentFinder
+ * @see SegmentFinder.PrescribedSegmentFinder
*/
@NonNull
public Builder setGraphemeSegmentFinder(@NonNull SegmentFinder graphemeSegmentFinder) {
@@ -1171,7 +1189,7 @@
*
* @see #getWordSegmentFinder()
* @see SegmentFinder
- * @see SegmentFinder.DefaultSegmentFinder
+ * @see SegmentFinder.PrescribedSegmentFinder
*/
@NonNull
public Builder setWordSegmentFinder(@NonNull SegmentFinder wordSegmentFinder) {
@@ -1193,7 +1211,7 @@
*
* @see #getLineSegmentFinder()
* @see SegmentFinder
- * @see SegmentFinder.DefaultSegmentFinder
+ * @see SegmentFinder.PrescribedSegmentFinder
*/
@NonNull
public Builder setLineSegmentFinder(@NonNull SegmentFinder lineSegmentFinder) {
@@ -1360,7 +1378,7 @@
breaks = GrowingArrayUtils.append(breaks, count++, start + offset);
}
}
- return new SegmentFinder.DefaultSegmentFinder(Arrays.copyOf(breaks, count));
+ return new SegmentFinder.PrescribedSegmentFinder(Arrays.copyOf(breaks, count));
}
/**
diff --git a/core/java/android/webkit/TEST_MAPPING b/core/java/android/webkit/TEST_MAPPING
index bd25200..c1bc6d7 100644
--- a/core/java/android/webkit/TEST_MAPPING
+++ b/core/java/android/webkit/TEST_MAPPING
@@ -9,6 +9,14 @@
]
},
{
+ "name": "CtsSdkSandboxWebkitTestCases",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ },
+ {
"name": "CtsHostsideWebViewTests",
"options": [
{
diff --git a/core/java/android/webkit/WebResourceError.java b/core/java/android/webkit/WebResourceError.java
index 11f1b6f1..4c87489 100644
--- a/core/java/android/webkit/WebResourceError.java
+++ b/core/java/android/webkit/WebResourceError.java
@@ -19,7 +19,7 @@
import android.annotation.SystemApi;
/**
- * Encapsulates information about errors occured during loading of web resources. See
+ * Encapsulates information about errors that occurred during loading of web resources. See
* {@link WebViewClient#onReceivedError(WebView, WebResourceRequest, WebResourceError) WebViewClient.onReceivedError(WebView, WebResourceRequest, WebResourceError)}
*/
public abstract class WebResourceError {
diff --git a/core/java/android/widget/MediaController.java b/core/java/android/widget/MediaController.java
index ff2e175..2bd5c88 100644
--- a/core/java/android/widget/MediaController.java
+++ b/core/java/android/widget/MediaController.java
@@ -218,6 +218,7 @@
p.width = mAnchor.getWidth();
p.x = anchorPos[0] + (mAnchor.getWidth() - p.width) / 2;
p.y = anchorPos[1] + mAnchor.getHeight() - mDecor.getMeasuredHeight();
+ p.token = mAnchor.getWindowToken();
}
// This is called whenever mAnchor's layout bound changes
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index b9b928e..d6c2d30 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -937,6 +937,13 @@
private List<Path> mHighlightPaths;
private List<Paint> mHighlightPaints;
private Highlights mHighlights;
+ private int[] mSearchResultHighlights = null;
+ private Paint mSearchResultHighlightPaint = null;
+ private Paint mFocusedSearchResultHighlightPaint = null;
+ private int mFocusedSearchResultHighlightColor = 0xFFFF9632;
+ private int mSearchResultHighlightColor = 0xFFFFFF00;
+
+ private int mFocusedSearchResultIndex = -1;
private int mGesturePreviewHighlightStart = -1;
private int mGesturePreviewHighlightEnd = -1;
private Paint mGesturePreviewHighlightPaint;
@@ -4030,6 +4037,8 @@
*/
private static class TextAppearanceAttributes {
int mTextColorHighlight = 0;
+ int mSearchResultHighlightColor = 0;
+ int mFocusedSearchResultHighlightColor = 0;
ColorStateList mTextColor = null;
ColorStateList mTextColorHint = null;
ColorStateList mTextColorLink = null;
@@ -4062,6 +4071,9 @@
public String toString() {
return "TextAppearanceAttributes {\n"
+ " mTextColorHighlight:" + mTextColorHighlight + "\n"
+ + " mSearchResultHighlightColor: " + mSearchResultHighlightColor + "\n"
+ + " mFocusedSearchResultHighlightColor: "
+ + mFocusedSearchResultHighlightColor + "\n"
+ " mTextColor:" + mTextColor + "\n"
+ " mTextColorHint:" + mTextColorHint + "\n"
+ " mTextColorLink:" + mTextColorLink + "\n"
@@ -4100,6 +4112,11 @@
static {
sAppearanceValues.put(com.android.internal.R.styleable.TextView_textColorHighlight,
com.android.internal.R.styleable.TextAppearance_textColorHighlight);
+ sAppearanceValues.put(com.android.internal.R.styleable.TextView_searchResultHighlightColor,
+ com.android.internal.R.styleable.TextAppearance_searchResultHighlightColor);
+ sAppearanceValues.put(
+ com.android.internal.R.styleable.TextView_focusedSearchResultHighlightColor,
+ com.android.internal.R.styleable.TextAppearance_focusedSearchResultHighlightColor);
sAppearanceValues.put(com.android.internal.R.styleable.TextView_textColor,
com.android.internal.R.styleable.TextAppearance_textColor);
sAppearanceValues.put(com.android.internal.R.styleable.TextView_textColorHint,
@@ -4174,6 +4191,16 @@
attributes.mTextColorHighlight =
appearance.getColor(attr, attributes.mTextColorHighlight);
break;
+ case com.android.internal.R.styleable.TextAppearance_searchResultHighlightColor:
+ attributes.mSearchResultHighlightColor =
+ appearance.getColor(attr, attributes.mSearchResultHighlightColor);
+ break;
+ case com.android.internal.R.styleable
+ .TextAppearance_focusedSearchResultHighlightColor:
+ attributes.mFocusedSearchResultHighlightColor =
+ appearance.getColor(attr,
+ attributes.mFocusedSearchResultHighlightColor);
+ break;
case com.android.internal.R.styleable.TextAppearance_textColor:
attributes.mTextColor = appearance.getColorStateList(attr);
break;
@@ -4290,6 +4317,14 @@
setHighlightColor(attributes.mTextColorHighlight);
}
+ if (attributes.mSearchResultHighlightColor != 0) {
+ setSearchResultHighlightColor(attributes.mSearchResultHighlightColor);
+ }
+
+ if (attributes.mFocusedSearchResultHighlightColor != 0) {
+ setFocusedSearchResultHighlightColor(attributes.mFocusedSearchResultHighlightColor);
+ }
+
if (attributes.mTextSize != -1) {
mTextSizeUnit = attributes.mTextSizeUnit;
setRawTextSize(attributes.mTextSize, true /* shouldRequestLayout */);
@@ -6176,6 +6211,238 @@
}
/**
+ * Sets the search result ranges with flatten range representation.
+ *
+ * Ranges are represented of flattened inclusive start and exclusive end integers array. The
+ * inclusive start offset of the {@code i}-th range is stored in {@code 2 * i}-th of the array.
+ * The exclusive end offset of the {@code i}-th range is stored in {@code 2* i + 1}-th of the
+ * array. For example, the two ranges: (1, 2) and (3, 4) are flattened into single int array
+ * [1, 2, 3, 4].
+ *
+ * TextView will render the search result with the highlights with specified color in the theme.
+ * If there is a focused search result, it is rendered with focused color. By calling this
+ * method, the focused search index will be cleared.
+ *
+ * @attr ref android.R.styleable#TextView_searchResultHighlightColor
+ * @attr ref android.R.styleable#TextAppearance_searchResultHighlightColor
+ * @attr ref android.R.styleable#TextView_focusedSearchResultHighlightColor
+ * @attr ref android.R.styleable#TextAppearance_focusedSearchResultHighlightColor
+ *
+ * @see #getSearchResultHighlights()
+ * @see #setFocusedSearchResultIndex(int)
+ * @see #getFocusedSearchResultIndex()
+ * @see #setSearchResultHighlightColor(int)
+ * @see #getSearchResultHighlightColor()
+ * @see #setFocusedSearchResultHighlightColor(int)
+ * @see #getFocusedSearchResultHighlightColor()
+ *
+ * @param ranges the flatten ranges of the search result. null for clear.
+ */
+ public void setSearchResultHighlights(@Nullable int... ranges) {
+ if (ranges == null) {
+ mSearchResultHighlights = null;
+ mHighlightPathsBogus = true;
+ return;
+ }
+ if (ranges.length % 2 == 1) {
+ throw new IllegalArgumentException(
+ "Flatten ranges must have even numbered elements");
+ }
+ for (int j = 0; j < ranges.length / 2; ++j) {
+ int start = ranges[j * 2];
+ int end = ranges[j * 2 + 1];
+ if (start > end) {
+ throw new IllegalArgumentException(
+ "Reverse range found in the flatten range: " + start + ", " + end + ""
+ + " at " + j + "-th range");
+ }
+ }
+ mHighlightPathsBogus = true;
+ mSearchResultHighlights = ranges;
+ mFocusedSearchResultIndex = FOCUSED_SEARCH_RESULT_INDEX_NONE;
+ invalidate();
+ }
+
+ /**
+ * Gets the current search result ranges.
+ *
+ * @see #setSearchResultHighlights(int[])
+ * @see #setFocusedSearchResultIndex(int)
+ * @see #getFocusedSearchResultIndex()
+ * @see #setSearchResultHighlightColor(int)
+ * @see #getSearchResultHighlightColor()
+ * @see #setFocusedSearchResultHighlightColor(int)
+ * @see #getFocusedSearchResultHighlightColor()
+ *
+ * @return a flatten search result ranges. null if not available.
+ */
+ @Nullable
+ public int[] getSearchResultHighlights() {
+ return mSearchResultHighlights;
+ }
+
+ /**
+ * A special index used for {@link #setFocusedSearchResultIndex(int)} and
+ * {@link #getFocusedSearchResultIndex()} inidicating there is no focused search result.
+ */
+ public static final int FOCUSED_SEARCH_RESULT_INDEX_NONE = -1;
+
+ /**
+ * Sets the focused search result index.
+ *
+ * The focused search result is drawn in a focused color.
+ * Calling {@link #FOCUSED_SEARCH_RESULT_INDEX_NONE} for clearing focused search result.
+ *
+ * This method must be called after setting search result ranges by
+ * {@link #setSearchResultHighlights(int[])}.
+ *
+ * @attr ref android.R.styleable#TextView_searchResultHighlightColor
+ * @attr ref android.R.styleable#TextAppearance_searchResultHighlightColor
+ * @attr ref android.R.styleable#TextView_focusedSearchResultHighlightColor
+ * @attr ref android.R.styleable#TextAppearance_focusedSearchResultHighlightColor
+ *
+ * @see #setSearchResultHighlights(int[])
+ * @see #getSearchResultHighlights()
+ * @see #setFocusedSearchResultIndex(int)
+ * @see #getFocusedSearchResultIndex()
+ * @see #setSearchResultHighlightColor(int)
+ * @see #getSearchResultHighlightColor()
+ * @see #setFocusedSearchResultHighlightColor(int)
+ * @see #getFocusedSearchResultHighlightColor()
+ *
+ * @param index a focused search index or {@link #FOCUSED_SEARCH_RESULT_INDEX_NONE}
+ */
+ public void setFocusedSearchResultIndex(int index) {
+ if (mSearchResultHighlights == null) {
+ throw new IllegalArgumentException("Search result range must be set beforehand.");
+ }
+ if (index < -1 || index >= mSearchResultHighlights.length / 2) {
+ throw new IllegalArgumentException("Focused index(" + index + ") must be larger than "
+ + "-1 and less than range count(" + (mSearchResultHighlights.length / 2) + ")");
+ }
+ mFocusedSearchResultIndex = index;
+ mHighlightPathsBogus = true;
+ invalidate();
+ }
+
+ /**
+ * Gets the focused search result index.
+ *
+ * @attr ref android.R.styleable#TextView_searchResultHighlightColor
+ * @attr ref android.R.styleable#TextAppearance_searchResultHighlightColor
+ * @attr ref android.R.styleable#TextView_focusedSearchResultHighlightColor
+ * @attr ref android.R.styleable#TextAppearance_focusedSearchResultHighlightColor
+ *
+ * @see #setSearchResultHighlights(int[])
+ * @see #getSearchResultHighlights()
+ * @see #setFocusedSearchResultIndex(int)
+ * @see #getFocusedSearchResultIndex()
+ * @see #setSearchResultHighlightColor(int)
+ * @see #getSearchResultHighlightColor()
+ * @see #setFocusedSearchResultHighlightColor(int)
+ * @see #getFocusedSearchResultHighlightColor()
+
+ * @return a focused search index or {@link #FOCUSED_SEARCH_RESULT_INDEX_NONE}
+ */
+ public int getFocusedSearchResultIndex() {
+ return mFocusedSearchResultIndex;
+ }
+
+ /**
+ * Sets the search result highlight color.
+ *
+ * @attr ref android.R.styleable#TextView_searchResultHighlightColor
+ * @attr ref android.R.styleable#TextAppearance_searchResultHighlightColor
+ * @attr ref android.R.styleable#TextView_focusedSearchResultHighlightColor
+ * @attr ref android.R.styleable#TextAppearance_focusedSearchResultHighlightColor
+ *
+ * @see #setSearchResultHighlights(int[])
+ * @see #getSearchResultHighlights()
+ * @see #setFocusedSearchResultIndex(int)
+ * @see #getFocusedSearchResultIndex()
+ * @see #setSearchResultHighlightColor(int)
+ * @see #getSearchResultHighlightColor()
+ * @see #setFocusedSearchResultHighlightColor(int)
+ * @see #getFocusedSearchResultHighlightColor()
+
+ * @param color a search result highlight color.
+ */
+ public void setSearchResultHighlightColor(@ColorInt int color) {
+ mSearchResultHighlightColor = color;
+ }
+
+ /**
+ * Gets the search result highlight color.
+ *
+ * @attr ref android.R.styleable#TextView_searchResultHighlightColor
+ * @attr ref android.R.styleable#TextAppearance_searchResultHighlightColor
+ * @attr ref android.R.styleable#TextView_focusedSearchResultHighlightColor
+ * @attr ref android.R.styleable#TextAppearance_focusedSearchResultHighlightColor
+ *
+ * @see #setSearchResultHighlights(int[])
+ * @see #getSearchResultHighlights()
+ * @see #setFocusedSearchResultIndex(int)
+ * @see #getFocusedSearchResultIndex()
+ * @see #setSearchResultHighlightColor(int)
+ * @see #getSearchResultHighlightColor()
+ * @see #setFocusedSearchResultHighlightColor(int)
+ * @see #getFocusedSearchResultHighlightColor()
+
+ * @return a search result highlight color.
+ */
+ @ColorInt
+ public int getSearchResultHighlightColor() {
+ return mSearchResultHighlightColor;
+ }
+
+ /**
+ * Sets focused search result highlight color.
+ *
+ * @attr ref android.R.styleable#TextView_searchResultHighlightColor
+ * @attr ref android.R.styleable#TextAppearance_searchResultHighlightColor
+ * @attr ref android.R.styleable#TextView_focusedSearchResultHighlightColor
+ * @attr ref android.R.styleable#TextAppearance_focusedSearchResultHighlightColor
+ *
+ * @see #setSearchResultHighlights(int[])
+ * @see #getSearchResultHighlights()
+ * @see #setFocusedSearchResultIndex(int)
+ * @see #getFocusedSearchResultIndex()
+ * @see #setSearchResultHighlightColor(int)
+ * @see #getSearchResultHighlightColor()
+ * @see #setFocusedSearchResultHighlightColor(int)
+ * @see #getFocusedSearchResultHighlightColor()
+
+ * @param color a focused search result highlight color.
+ */
+ public void setFocusedSearchResultHighlightColor(@ColorInt int color) {
+ mFocusedSearchResultHighlightColor = color;
+ }
+
+ /**
+ * Gets focused search result highlight color.
+ *
+ * @attr ref android.R.styleable#TextView_searchResultHighlightColor
+ * @attr ref android.R.styleable#TextAppearance_searchResultHighlightColor
+ * @attr ref android.R.styleable#TextView_focusedSearchResultHighlightColor
+ * @attr ref android.R.styleable#TextAppearance_focusedSearchResultHighlightColor
+ *
+ * @see #setSearchResultHighlights(int[])
+ * @see #getSearchResultHighlights()
+ * @see #setFocusedSearchResultIndex(int)
+ * @see #getFocusedSearchResultIndex()
+ * @see #setSearchResultHighlightColor(int)
+ * @see #getSearchResultHighlightColor()
+ * @see #setFocusedSearchResultHighlightColor(int)
+ * @see #getFocusedSearchResultHighlightColor()
+
+ * @return a focused search result highlight color.
+ */
+ @ColorInt
+ public int getFocusedSearchResultHighlightColor() {
+ return mFocusedSearchResultHighlightColor;
+ }
+
+ /**
* Highlights the text range (from inclusive start offset to exclusive end offset) to show what
* will be selected by the ongoing select handwriting gesture. While the gesture preview
* highlight is shown, the selection or cursor is hidden. If the text or selection is changed,
@@ -8335,7 +8602,6 @@
for (int i = 0; i < mHighlights.getSize(); ++i) {
final int[] ranges = mHighlights.getRanges(i);
final Paint paint = mHighlights.getPaint(i);
-
final Path path;
if (mPathRecyclePool.isEmpty()) {
path = new Path();
@@ -8363,6 +8629,8 @@
}
}
+ addSearchHighlightPaths();
+
if (hasGesturePreviewHighlight()) {
final Path path;
if (mPathRecyclePool.isEmpty()) {
@@ -8381,6 +8649,67 @@
mHighlightPathsBogus = false;
}
+ private void addSearchHighlightPaths() {
+ if (mSearchResultHighlights != null) {
+ final Path searchResultPath;
+ if (mPathRecyclePool.isEmpty()) {
+ searchResultPath = new Path();
+ } else {
+ searchResultPath = mPathRecyclePool.get(mPathRecyclePool.size() - 1);
+ mPathRecyclePool.remove(mPathRecyclePool.size() - 1);
+ searchResultPath.reset();
+ }
+ final Path focusedSearchResultPath;
+ if (mFocusedSearchResultIndex == FOCUSED_SEARCH_RESULT_INDEX_NONE) {
+ focusedSearchResultPath = null;
+ } else if (mPathRecyclePool.isEmpty()) {
+ focusedSearchResultPath = new Path();
+ } else {
+ focusedSearchResultPath = mPathRecyclePool.get(mPathRecyclePool.size() - 1);
+ mPathRecyclePool.remove(mPathRecyclePool.size() - 1);
+ focusedSearchResultPath.reset();
+ }
+
+ boolean atLeastOnePathAdded = false;
+ for (int j = 0; j < mSearchResultHighlights.length / 2; ++j) {
+ final int start = mSearchResultHighlights[2 * j];
+ final int end = mSearchResultHighlights[2 * j + 1];
+ if (start < end) {
+ if (j == mFocusedSearchResultIndex) {
+ mLayout.getSelection(start, end, (left, top, right, bottom, layout) ->
+ focusedSearchResultPath.addRect(left, top, right, bottom,
+ Path.Direction.CW)
+ );
+ } else {
+ mLayout.getSelection(start, end, (left, top, right, bottom, layout) ->
+ searchResultPath.addRect(left, top, right, bottom,
+ Path.Direction.CW)
+ );
+ atLeastOnePathAdded = true;
+ }
+ }
+ }
+ if (atLeastOnePathAdded) {
+ if (mSearchResultHighlightPaint == null) {
+ mSearchResultHighlightPaint = new Paint();
+ }
+ mSearchResultHighlightPaint.setColor(mSearchResultHighlightColor);
+ mSearchResultHighlightPaint.setStyle(Paint.Style.FILL);
+ mHighlightPaths.add(searchResultPath);
+ mHighlightPaints.add(mSearchResultHighlightPaint);
+ }
+ if (focusedSearchResultPath != null) {
+ if (mFocusedSearchResultHighlightPaint == null) {
+ mFocusedSearchResultHighlightPaint = new Paint();
+ }
+ mFocusedSearchResultHighlightPaint.setColor(mFocusedSearchResultHighlightColor);
+ mFocusedSearchResultHighlightPaint.setStyle(Paint.Style.FILL);
+ mHighlightPaths.add(focusedSearchResultPath);
+ mHighlightPaints.add(mFocusedSearchResultHighlightPaint);
+ }
+ }
+ }
+
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private Path getUpdatedHighlightPath() {
Path highlight = null;
@@ -10826,6 +11155,26 @@
* This has to be called after layout. Returns true if anything changed.
*/
public boolean bringPointIntoView(int offset) {
+ return bringPointIntoView(offset, false);
+ }
+
+ /**
+ * Move the insertion position of the given offset into visible area of the View.
+ *
+ * If the View is focused or {@code requestRectWithoutFocus} is set to true, this API may call
+ * {@link View#requestRectangleOnScreen(Rect)} to bring the point to the visible area if
+ * necessary.
+ *
+ * @param offset an offset of the character.
+ * @param requestRectWithoutFocus True for calling {@link View#requestRectangleOnScreen(Rect)}
+ * in the unfocused state. False for calling it only the View has
+ * the focus.
+ * @return true if anything changed, otherwise false.
+ *
+ * @see #bringPointIntoView(int)
+ */
+ public boolean bringPointIntoView(@IntRange(from = 0) int offset,
+ boolean requestRectWithoutFocus) {
if (isLayoutRequested()) {
mDeferScroll = offset;
return false;
@@ -11002,7 +11351,7 @@
changed = true;
}
- if (isFocused()) {
+ if (requestRectWithoutFocus && isFocused()) {
// This offsets because getInterestingRect() is in terms of viewport coordinates, but
// requestRectangleOnScreen() is in terms of content coordinates.
@@ -13245,7 +13594,7 @@
* Creates the {@link TextBoundsInfo} for the text lines that intersects with the {@code rectF}.
* @hide
*/
- public TextBoundsInfo getTextBoundsInfo(@NonNull RectF rectF) {
+ public TextBoundsInfo getTextBoundsInfo(@NonNull RectF bounds) {
final Layout layout = getLayout();
if (layout == null) {
// No valid text layout, return null.
@@ -13268,19 +13617,18 @@
final float layoutLeft = viewportToContentHorizontalOffset();
final float layoutTop = viewportToContentVerticalOffset();
- final RectF localRectF = new RectF(rectF);
- globalToLocalMatrix.mapRect(localRectF);
- localRectF.offset(-layoutLeft, -layoutTop);
+ final RectF localBounds = new RectF(bounds);
+ globalToLocalMatrix.mapRect(localBounds);
+ localBounds.offset(-layoutLeft, -layoutTop);
// Text length is 0. There is no character bounds, return empty TextBoundsInfo.
// rectF doesn't intersect with the layout, return empty TextBoundsInfo.
- if (!localRectF.intersects(0f, 0f, layout.getWidth(), layout.getHeight())
+ if (!localBounds.intersects(0f, 0f, layout.getWidth(), layout.getHeight())
|| text.length() == 0) {
- final TextBoundsInfo.Builder builder = new TextBoundsInfo.Builder();
+ final TextBoundsInfo.Builder builder = new TextBoundsInfo.Builder(0, 0);
final SegmentFinder emptySegmentFinder =
- new SegmentFinder.DefaultSegmentFinder(new int[0]);
- builder.setStartAndEnd(0, 0)
- .setMatrix(localToGlobalMatrix)
+ new SegmentFinder.PrescribedSegmentFinder(new int[0]);
+ builder.setMatrix(localToGlobalMatrix)
.setCharacterBounds(new float[0])
.setCharacterBidiLevel(new int[0])
.setCharacterFlags(new int[0])
@@ -13290,8 +13638,8 @@
return builder.build();
}
- final int startLine = layout.getLineForVertical((int) Math.floor(localRectF.top));
- final int endLine = layout.getLineForVertical((int) Math.floor(localRectF.bottom));
+ final int startLine = layout.getLineForVertical((int) Math.floor(localBounds.top));
+ final int endLine = layout.getLineForVertical((int) Math.floor(localBounds.bottom));
final int start = layout.getLineStart(startLine);
final int end = layout.getLineEnd(endLine);
@@ -13349,18 +13697,18 @@
lineRanges[2 * offset] = layout.getLineStart(line);
lineRanges[2 * offset + 1] = layout.getLineEnd(line);
}
- final SegmentFinder lineSegmentFinder = new SegmentFinder.DefaultSegmentFinder(lineRanges);
+ final SegmentFinder lineSegmentFinder =
+ new SegmentFinder.PrescribedSegmentFinder(lineRanges);
- final TextBoundsInfo.Builder builder = new TextBoundsInfo.Builder();
- builder.setStartAndEnd(start, end)
+ return new TextBoundsInfo.Builder(start, end)
.setMatrix(localToGlobalMatrix)
.setCharacterBounds(characterBounds)
.setCharacterBidiLevel(characterBidiLevels)
.setCharacterFlags(characterFlags)
.setGraphemeSegmentFinder(graphemeSegmentFinder)
.setLineSegmentFinder(lineSegmentFinder)
- .setWordSegmentFinder(wordSegmentFinder);
- return builder.build();
+ .setWordSegmentFinder(wordSegmentFinder)
+ .build();
}
/**
diff --git a/core/java/android/window/TaskFragmentOperation.java b/core/java/android/window/TaskFragmentOperation.java
index 3272c3b..0d6a58b 100644
--- a/core/java/android/window/TaskFragmentOperation.java
+++ b/core/java/android/window/TaskFragmentOperation.java
@@ -58,14 +58,17 @@
/** Sets two TaskFragments adjacent to each other. */
public static final int OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS = 4;
+ /** Clears the adjacent TaskFragments relationship. */
+ public static final int OP_TYPE_CLEAR_ADJACENT_TASK_FRAGMENTS = 5;
+
/** Requests focus on the top running Activity in the given TaskFragment. */
- public static final int OP_TYPE_REQUEST_FOCUS_ON_TASK_FRAGMENT = 5;
+ public static final int OP_TYPE_REQUEST_FOCUS_ON_TASK_FRAGMENT = 6;
/** Sets a given TaskFragment to have a companion TaskFragment. */
- public static final int OP_TYPE_SET_COMPANION_TASK_FRAGMENT = 6;
+ public static final int OP_TYPE_SET_COMPANION_TASK_FRAGMENT = 7;
/** Sets the {@link TaskFragmentAnimationParams} for the given TaskFragment. */
- public static final int OP_TYPE_SET_ANIMATION_PARAMS = 7;
+ public static final int OP_TYPE_SET_ANIMATION_PARAMS = 8;
@IntDef(prefix = { "OP_TYPE_" }, value = {
OP_TYPE_UNKNOWN,
@@ -74,6 +77,7 @@
OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT,
OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT,
OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS,
+ OP_TYPE_CLEAR_ADJACENT_TASK_FRAGMENTS,
OP_TYPE_REQUEST_FOCUS_ON_TASK_FRAGMENT,
OP_TYPE_SET_COMPANION_TASK_FRAGMENT,
OP_TYPE_SET_ANIMATION_PARAMS
diff --git a/core/java/android/window/WindowContainerTransaction.java b/core/java/android/window/WindowContainerTransaction.java
index 80b2161..cc48d46 100644
--- a/core/java/android/window/WindowContainerTransaction.java
+++ b/core/java/android/window/WindowContainerTransaction.java
@@ -16,6 +16,7 @@
package android.window;
+import static android.window.TaskFragmentOperation.OP_TYPE_CLEAR_ADJACENT_TASK_FRAGMENTS;
import static android.window.TaskFragmentOperation.OP_TYPE_CREATE_TASK_FRAGMENT;
import static android.window.TaskFragmentOperation.OP_TYPE_DELETE_TASK_FRAGMENT;
import static android.window.TaskFragmentOperation.OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT;
@@ -582,16 +583,14 @@
* {@link #setAdjacentRoots(WindowContainerToken, WindowContainerToken)}, but can be used with
* fragmentTokens when that TaskFragments haven't been created (but will be created in the same
* {@link WindowContainerTransaction}).
- * To reset it, pass {@code null} for {@code fragmentToken2}.
* @param fragmentToken1 client assigned unique token to create TaskFragment with specified
* in {@link TaskFragmentCreationParams#getFragmentToken()}.
* @param fragmentToken2 client assigned unique token to create TaskFragment with specified
- * in {@link TaskFragmentCreationParams#getFragmentToken()}. If it is
- * {@code null}, the transaction will reset the adjacent TaskFragment.
+ * in {@link TaskFragmentCreationParams#getFragmentToken()}.
*/
@NonNull
public WindowContainerTransaction setAdjacentTaskFragments(
- @NonNull IBinder fragmentToken1, @Nullable IBinder fragmentToken2,
+ @NonNull IBinder fragmentToken1, @NonNull IBinder fragmentToken2,
@Nullable TaskFragmentAdjacentParams params) {
final TaskFragmentOperation operation = new TaskFragmentOperation.Builder(
OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS)
@@ -602,6 +601,21 @@
}
/**
+ * Clears the adjacent TaskFragments relationship that is previously set through
+ * {@link #setAdjacentTaskFragments}. Clear operation on one TaskFragment will also clear its
+ * current adjacent TaskFragment's.
+ * @param fragmentToken client assigned unique token to create TaskFragment with specified
+ * in {@link TaskFragmentCreationParams#getFragmentToken()}.
+ */
+ @NonNull
+ public WindowContainerTransaction clearAdjacentTaskFragments(@NonNull IBinder fragmentToken) {
+ final TaskFragmentOperation operation = new TaskFragmentOperation.Builder(
+ OP_TYPE_CLEAR_ADJACENT_TASK_FRAGMENTS)
+ .build();
+ return addTaskFragmentOperation(fragmentToken, operation);
+ }
+
+ /**
* If `container` was brought to front as a transient-launch (eg. recents), this will reorder
* the container back to where it was prior to the transient-launch. This way if a transient
* launch is "aborted", the z-ordering of containers in WM should be restored to before the
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 02cbd41..9f283d4 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -2953,12 +2953,24 @@
private boolean shouldShowStickyContentPreviewNoOrientationCheck() {
return shouldShowTabs()
- && mMultiProfilePagerAdapter.getListAdapterForUserHandle(
- UserHandle.of(UserHandle.myUserId())).getCount() > 0
+ && (mMultiProfilePagerAdapter.getListAdapterForUserHandle(
+ UserHandle.of(UserHandle.myUserId())).getCount() > 0
+ || shouldShowContentPreviewWhenEmpty())
&& shouldShowContentPreview();
}
/**
+ * This method could be used to override the default behavior when we hide the preview area
+ * when the current tab doesn't have any items.
+ *
+ * @return true if we want to show the content preview area even if the tab for the current
+ * user is empty
+ */
+ protected boolean shouldShowContentPreviewWhenEmpty() {
+ return false;
+ }
+
+ /**
* @return true if we want to show the content preview area
*/
protected boolean shouldShowContentPreview() {
diff --git a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
index b9ca557..88d6425 100644
--- a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
+++ b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
@@ -27,6 +27,7 @@
import android.os.PersistableBundle;
import android.os.RemoteCallback;
import android.os.SharedMemory;
+import android.service.voice.IVisualQueryDetectionVoiceInteractionCallback;
import android.service.voice.IMicrophoneHotwordDetectionVoiceInteractionCallback;
import android.service.voice.IVoiceInteractionService;
import android.service.voice.IVoiceInteractionSession;
@@ -299,6 +300,10 @@
*/
void shutdownHotwordDetectionService();
+ void startPerceiving(in IVisualQueryDetectionVoiceInteractionCallback callback);
+
+ void stopPerceiving();
+
void startListeningFromMic(
in AudioFormat audioFormat,
in IMicrophoneHotwordDetectionVoiceInteractionCallback callback);
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 0706ee5..f098e2c 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -209,7 +209,7 @@
* <p>Can only be used if there is a work profile.
* <p>Possible values can be either {@link #PROFILE_PERSONAL} or {@link #PROFILE_WORK}.
*/
- static final String EXTRA_SELECTED_PROFILE =
+ protected static final String EXTRA_SELECTED_PROFILE =
"com.android.internal.app.ResolverActivity.EXTRA_SELECTED_PROFILE";
/**
@@ -224,8 +224,8 @@
static final String EXTRA_CALLING_USER =
"com.android.internal.app.ResolverActivity.EXTRA_CALLING_USER";
- static final int PROFILE_PERSONAL = AbstractMultiProfilePagerAdapter.PROFILE_PERSONAL;
- static final int PROFILE_WORK = AbstractMultiProfilePagerAdapter.PROFILE_WORK;
+ protected static final int PROFILE_PERSONAL = AbstractMultiProfilePagerAdapter.PROFILE_PERSONAL;
+ protected static final int PROFILE_WORK = AbstractMultiProfilePagerAdapter.PROFILE_WORK;
private BroadcastReceiver mWorkProfileStateReceiver;
private UserHandle mHeaderCreatorUser;
diff --git a/core/java/com/android/internal/app/UnlaunchableAppActivity.java b/core/java/com/android/internal/app/UnlaunchableAppActivity.java
index 0776572..e47c335 100644
--- a/core/java/com/android/internal/app/UnlaunchableAppActivity.java
+++ b/core/java/com/android/internal/app/UnlaunchableAppActivity.java
@@ -28,11 +28,13 @@
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentSender;
+import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
import android.os.UserManager;
+import android.telecom.TelecomManager;
import android.util.Log;
import android.view.Window;
@@ -52,6 +54,7 @@
private int mUserId;
private int mReason;
private IntentSender mTarget;
+ private TelecomManager mTelecomManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -60,9 +63,11 @@
// TODO: Use AlertActivity so we don't need to hide title bar and create a dialog
requestWindowFeature(Window.FEATURE_NO_TITLE);
Intent intent = getIntent();
+ mTelecomManager = getSystemService(TelecomManager.class);
mReason = intent.getIntExtra(EXTRA_UNLAUNCHABLE_REASON, -1);
mUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
- mTarget = intent.getParcelableExtra(Intent.EXTRA_INTENT, android.content.IntentSender.class);
+ mTarget = intent.getParcelableExtra(Intent.EXTRA_INTENT,
+ android.content.IntentSender.class);
if (mUserId == UserHandle.USER_NULL) {
Log.wtf(TAG, "Invalid user id: " + mUserId + ". Stopping.");
@@ -70,29 +75,40 @@
return;
}
- String dialogTitle;
- String dialogMessage = null;
- if (mReason == UNLAUNCHABLE_REASON_QUIET_MODE) {
- dialogTitle = getDialogTitle();
- dialogMessage = getDialogMessage();
- } else {
+ if (mReason != UNLAUNCHABLE_REASON_QUIET_MODE) {
Log.wtf(TAG, "Invalid unlaunchable type: " + mReason);
finish();
return;
}
- AlertDialog.Builder builder = new AlertDialog.Builder(this)
- .setTitle(dialogTitle)
- .setMessage(dialogMessage)
- .setOnDismissListener(this);
- if (mReason == UNLAUNCHABLE_REASON_QUIET_MODE) {
- builder.setPositiveButton(R.string.work_mode_turn_on, this)
- .setNegativeButton(R.string.cancel, null);
+ String targetPackageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME);
+ boolean showEmergencyCallButton =
+ (targetPackageName != null && targetPackageName.equals(
+ mTelecomManager.getDefaultDialerPackage(UserHandle.of(mUserId))));
+
+ final AlertDialog.Builder builder;
+ final String dialogMessage;
+ if (showEmergencyCallButton) {
+ builder = new AlertDialog.Builder(this, R.style.AlertDialogWithEmergencyButton);
+ dialogMessage = getDialogMessage(R.string.work_mode_dialer_off_message);
+ builder.setNeutralButton(R.string.work_mode_emergency_call_button, this);
} else {
- builder.setPositiveButton(R.string.ok, null);
+ builder = new AlertDialog.Builder(this);
+ dialogMessage = getDialogMessage(R.string.work_mode_off_message);
}
+ builder.setTitle(getDialogTitle())
+ .setMessage(dialogMessage)
+ .setOnDismissListener(this)
+ .setPositiveButton(R.string.work_mode_turn_on, this)
+ .setNegativeButton(R.string.cancel, null);
+
final AlertDialog dialog = builder.create();
dialog.create();
+ if (showEmergencyCallButton) {
+ dialog.getWindow().findViewById(R.id.parentPanel).setPadding(0, 0, 0, 30);
+ dialog.getWindow().findViewById(R.id.button3).setOutlineProvider(null);
+ }
+
// Prevents screen overlay attack.
getWindow().setHideOverlayWindows(true);
dialog.getButton(DialogInterface.BUTTON_POSITIVE).setFilterTouchesWhenObscured(true);
@@ -104,10 +120,10 @@
UNLAUNCHABLE_APP_WORK_PAUSED_TITLE, () -> getString(R.string.work_mode_off_title));
}
- private String getDialogMessage() {
+ private String getDialogMessage(int dialogMessageString) {
return getSystemService(DevicePolicyManager.class).getResources().getString(
UNLAUNCHABLE_APP_WORK_PAUSED_MESSAGE,
- () -> getString(R.string.work_mode_off_message));
+ () -> getString(dialogMessageString));
}
@Override
@@ -117,14 +133,27 @@
@Override
public void onClick(DialogInterface dialog, int which) {
- if (mReason == UNLAUNCHABLE_REASON_QUIET_MODE && which == DialogInterface.BUTTON_POSITIVE) {
+ if (mReason != UNLAUNCHABLE_REASON_QUIET_MODE) {
+ return;
+ }
+ if (which == DialogInterface.BUTTON_POSITIVE) {
UserManager userManager = UserManager.get(this);
new Handler(Looper.getMainLooper()).post(
() -> userManager.requestQuietModeEnabled(
/* enableQuietMode= */ false, UserHandle.of(mUserId), mTarget));
+ } else if (which == DialogInterface.BUTTON_NEUTRAL) {
+ launchEmergencyDialer();
}
}
+ private void launchEmergencyDialer() {
+ startActivity(mTelecomManager.createLaunchEmergencyDialerIntent(
+ null /* number*/)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
+ | Intent.FLAG_ACTIVITY_CLEAR_TOP));
+ }
+
private static final Intent createBaseIntent() {
Intent intent = new Intent();
intent.setComponent(new ComponentName("android", UnlaunchableAppActivity.class.getName()));
@@ -139,9 +168,13 @@
return intent;
}
- public static Intent createInQuietModeDialogIntent(int userId, IntentSender target) {
+ public static Intent createInQuietModeDialogIntent(int userId, IntentSender target,
+ ResolveInfo resolveInfo) {
Intent intent = createInQuietModeDialogIntent(userId);
intent.putExtra(Intent.EXTRA_INTENT, target);
+ if (resolveInfo != null) {
+ intent.putExtra(Intent.EXTRA_PACKAGE_NAME, resolveInfo.getComponentInfo().packageName);
+ }
return intent;
}
}
diff --git a/core/java/com/android/internal/inputmethod/EditableInputConnection.java b/core/java/com/android/internal/inputmethod/EditableInputConnection.java
index 52e7471..8690e8d 100644
--- a/core/java/com/android/internal/inputmethod/EditableInputConnection.java
+++ b/core/java/com/android/internal/inputmethod/EditableInputConnection.java
@@ -271,9 +271,9 @@
@Override
public void requestTextBoundsInfo(
- @NonNull RectF rectF, @Nullable @CallbackExecutor Executor executor,
+ @NonNull RectF bounds, @Nullable @CallbackExecutor Executor executor,
@NonNull Consumer<TextBoundsInfoResult> consumer) {
- final TextBoundsInfo textBoundsInfo = mTextView.getTextBoundsInfo(rectF);
+ final TextBoundsInfo textBoundsInfo = mTextView.getTextBoundsInfo(bounds);
final int resultCode;
if (textBoundsInfo != null) {
resultCode = TextBoundsInfoResult.CODE_SUCCESS;
diff --git a/core/java/com/android/internal/inputmethod/IRemoteInputConnection.aidl b/core/java/com/android/internal/inputmethod/IRemoteInputConnection.aidl
index 65016c2..b375936 100644
--- a/core/java/com/android/internal/inputmethod/IRemoteInputConnection.aidl
+++ b/core/java/com/android/internal/inputmethod/IRemoteInputConnection.aidl
@@ -111,7 +111,7 @@
int cursorUpdateMode, int cursorUpdateFilter, int imeDisplayId,
in AndroidFuture future /* T=Boolean */);
- void requestTextBoundsInfo(in InputConnectionCommandHeader header, in RectF rect,
+ void requestTextBoundsInfo(in InputConnectionCommandHeader header, in RectF bounds,
in ResultReceiver resultReceiver /* T=TextBoundsInfoResult */);
void commitContent(in InputConnectionCommandHeader header, in InputContentInfo inputContentInfo,
diff --git a/core/java/com/android/internal/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java
index d9e9a5f..95a47ea 100644
--- a/core/java/com/android/internal/jank/InteractionJankMonitor.java
+++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java
@@ -16,11 +16,15 @@
package com.android.internal.jank;
+import static android.Manifest.permission.READ_DEVICE_CONFIG;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+
import static com.android.internal.jank.FrameTracker.REASON_CANCEL_NORMAL;
import static com.android.internal.jank.FrameTracker.REASON_CANCEL_TIMEOUT;
import static com.android.internal.jank.FrameTracker.REASON_END_NORMAL;
import static com.android.internal.jank.FrameTracker.REASON_END_UNKNOWN;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__BIOMETRIC_PROMPT_TRANSITION;
+import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__IME_INSETS_ANIMATION;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_ALL_APPS_SCROLL;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_CLOSE_TO_HOME;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_CLOSE_TO_PIP;
@@ -89,17 +93,19 @@
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__VOLUME_CONTROL;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__WALLPAPER_TRANSITION;
+import android.Manifest;
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
import android.annotation.UiThread;
import android.annotation.WorkerThread;
+import android.app.ActivityThread;
import android.content.Context;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.HandlerThread;
import android.provider.DeviceConfig;
-import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
@@ -232,6 +238,7 @@
public static final int CUJ_LAUNCHER_APP_SWIPE_TO_RECENTS = 66;
public static final int CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE = 67;
public static final int CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME = 68;
+ public static final int CUJ_IME_INSETS_ANIMATION = 69;
private static final int NO_STATSD_LOGGING = -1;
@@ -309,6 +316,7 @@
UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_SWIPE_TO_RECENTS,
UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_CLOSE_ALL_APPS_SWIPE,
UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_CLOSE_ALL_APPS_TO_HOME,
+ UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__IME_INSETS_ANIMATION,
};
private static class InstanceHolder {
@@ -401,7 +409,8 @@
CUJ_RECENTS_SCROLLING,
CUJ_LAUNCHER_APP_SWIPE_TO_RECENTS,
CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE,
- CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME
+ CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME,
+ CUJ_IME_INSETS_ANIMATION,
})
@Retention(RetentionPolicy.SOURCE)
public @interface CujType {
@@ -422,29 +431,37 @@
* @param worker the worker thread for the callbacks
*/
@VisibleForTesting
+ @RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
public InteractionJankMonitor(@NonNull HandlerThread worker) {
- // Check permission early.
- Settings.Config.enforceReadPermission(
- DeviceConfig.NAMESPACE_INTERACTION_JANK_MONITOR);
-
mRunningTrackers = new SparseArray<>();
mTimeoutActions = new SparseArray<>();
mWorker = worker;
mWorker.start();
- mSamplingInterval = DEFAULT_SAMPLING_INTERVAL;
mDisplayResolutionTracker = new DisplayResolutionTracker(worker.getThreadHandler());
-
- // Post initialization to the background in case we're running on the main
- // thread.
- mWorker.getThreadHandler().post(
- () -> mPropertiesChangedListener.onPropertiesChanged(
- DeviceConfig.getProperties(
- DeviceConfig.NAMESPACE_INTERACTION_JANK_MONITOR)));
- DeviceConfig.addOnPropertiesChangedListener(
- DeviceConfig.NAMESPACE_INTERACTION_JANK_MONITOR,
- new HandlerExecutor(mWorker.getThreadHandler()),
- mPropertiesChangedListener);
+ mSamplingInterval = DEFAULT_SAMPLING_INTERVAL;
mEnabled = DEFAULT_ENABLED;
+
+ final Context context = ActivityThread.currentApplication();
+ if (context.checkCallingOrSelfPermission(READ_DEVICE_CONFIG) == PERMISSION_GRANTED) {
+ // Post initialization to the background in case we're running on the main thread.
+ mWorker.getThreadHandler().post(
+ () -> mPropertiesChangedListener.onPropertiesChanged(
+ DeviceConfig.getProperties(
+ DeviceConfig.NAMESPACE_INTERACTION_JANK_MONITOR)));
+ DeviceConfig.addOnPropertiesChangedListener(
+ DeviceConfig.NAMESPACE_INTERACTION_JANK_MONITOR,
+ new HandlerExecutor(mWorker.getThreadHandler()),
+ mPropertiesChangedListener);
+ } else {
+ if (DEBUG) {
+ Log.d(TAG, "Initialized the InteractionJankMonitor."
+ + " (No READ_DEVICE_CONFIG permission to change configs)"
+ + " enabled=" + mEnabled + ", interval=" + mSamplingInterval
+ + ", missedFrameThreshold=" + mTraceThresholdMissedFrames
+ + ", frameTimeThreshold=" + mTraceThresholdFrameTimeMillis
+ + ", package=" + context.getPackageName());
+ }
+ }
}
/**
@@ -923,6 +940,8 @@
return "LAUNCHER_CLOSE_ALL_APPS_SWIPE";
case CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME:
return "LAUNCHER_CLOSE_ALL_APPS_TO_HOME";
+ case CUJ_IME_INSETS_ANIMATION:
+ return "IME_INSETS_ANIMATION";
}
return "UNKNOWN";
}
@@ -1178,7 +1197,7 @@
*/
@VisibleForTesting
public int getDisplayId() {
- return (mSurfaceOnly ? mContext.getDisplay() : mView.getDisplay()).getDisplayId();
+ return mSurfaceOnly ? mContext.getDisplayId() : mView.getContext().getDisplayId();
}
}
diff --git a/core/java/com/android/internal/os/BatteryStatsHistory.java b/core/java/com/android/internal/os/BatteryStatsHistory.java
index 3d8982b..04b7239cb 100644
--- a/core/java/com/android/internal/os/BatteryStatsHistory.java
+++ b/core/java/com/android/internal/os/BatteryStatsHistory.java
@@ -187,8 +187,6 @@
private int mNextHistoryTagIdx = 0;
private int mNumHistoryTagChars = 0;
private int mHistoryBufferLastPos = -1;
- private int mActiveHistoryStates = 0xffffffff;
- private int mActiveHistoryStates2 = 0xffffffff;
private long mLastHistoryElapsedRealtimeMs = 0;
private long mTrackRunningHistoryElapsedRealtimeMs = 0;
private long mTrackRunningHistoryUptimeMs = 0;
@@ -362,8 +360,6 @@
mNextHistoryTagIdx = 0;
mNumHistoryTagChars = 0;
mHistoryBufferLastPos = -1;
- mActiveHistoryStates = 0xffffffff;
- mActiveHistoryStates2 = 0xffffffff;
if (mStepDetailsCalculator != null) {
mStepDetailsCalculator.clear();
}
@@ -1098,8 +1094,9 @@
*/
public void recordScreenBrightnessEvent(long elapsedRealtimeMs, long uptimeMs,
int brightnessBin) {
- mHistoryCur.states = (mHistoryCur.states & ~HistoryItem.STATE_BRIGHTNESS_MASK)
- | (brightnessBin << HistoryItem.STATE_BRIGHTNESS_SHIFT);
+ mHistoryCur.states = setBitField(mHistoryCur.states, brightnessBin,
+ HistoryItem.STATE_BRIGHTNESS_SHIFT,
+ HistoryItem.STATE_BRIGHTNESS_MASK);
writeHistoryItem(elapsedRealtimeMs, uptimeMs);
}
@@ -1108,8 +1105,9 @@
*/
public void recordGpsSignalQualityEvent(long elapsedRealtimeMs, long uptimeMs,
int signalLevel) {
- mHistoryCur.states2 = (mHistoryCur.states2 & ~HistoryItem.STATE2_GPS_SIGNAL_QUALITY_MASK)
- | (signalLevel << HistoryItem.STATE2_GPS_SIGNAL_QUALITY_SHIFT);
+ mHistoryCur.states2 = setBitField(mHistoryCur.states2, signalLevel,
+ HistoryItem.STATE2_GPS_SIGNAL_QUALITY_SHIFT,
+ HistoryItem.STATE2_GPS_SIGNAL_QUALITY_MASK);
writeHistoryItem(elapsedRealtimeMs, uptimeMs);
}
@@ -1117,8 +1115,9 @@
* Records a device idle mode change event.
*/
public void recordDeviceIdleEvent(long elapsedRealtimeMs, long uptimeMs, int mode) {
- mHistoryCur.states2 = (mHistoryCur.states2 & ~HistoryItem.STATE2_DEVICE_IDLE_MASK)
- | (mode << HistoryItem.STATE2_DEVICE_IDLE_SHIFT);
+ mHistoryCur.states2 = setBitField(mHistoryCur.states2, mode,
+ HistoryItem.STATE2_DEVICE_IDLE_SHIFT,
+ HistoryItem.STATE2_DEVICE_IDLE_MASK);
writeHistoryItem(elapsedRealtimeMs, uptimeMs);
}
@@ -1130,13 +1129,15 @@
mHistoryCur.states = (mHistoryCur.states | addStateFlag) & ~removeStateFlag;
if (state != -1) {
mHistoryCur.states =
- (mHistoryCur.states & ~HistoryItem.STATE_PHONE_STATE_MASK)
- | (state << HistoryItem.STATE_PHONE_STATE_SHIFT);
+ setBitField(mHistoryCur.states, state,
+ HistoryItem.STATE_PHONE_STATE_SHIFT,
+ HistoryItem.STATE_PHONE_STATE_MASK);
}
if (signalStrength != -1) {
mHistoryCur.states =
- (mHistoryCur.states & ~HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_MASK)
- | (signalStrength << HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_SHIFT);
+ setBitField(mHistoryCur.states, signalStrength,
+ HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_SHIFT,
+ HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_MASK);
}
writeHistoryItem(elapsedRealtimeMs, uptimeMs);
}
@@ -1146,8 +1147,9 @@
*/
public void recordDataConnectionTypeChangeEvent(long elapsedRealtimeMs, long uptimeMs,
int dataConnectionType) {
- mHistoryCur.states = (mHistoryCur.states & ~HistoryItem.STATE_DATA_CONNECTION_MASK)
- | (dataConnectionType << HistoryItem.STATE_DATA_CONNECTION_SHIFT);
+ mHistoryCur.states = setBitField(mHistoryCur.states, dataConnectionType,
+ HistoryItem.STATE_DATA_CONNECTION_SHIFT,
+ HistoryItem.STATE_DATA_CONNECTION_MASK);
writeHistoryItem(elapsedRealtimeMs, uptimeMs);
}
@@ -1157,8 +1159,9 @@
public void recordWifiSupplicantStateChangeEvent(long elapsedRealtimeMs, long uptimeMs,
int supplState) {
mHistoryCur.states2 =
- (mHistoryCur.states2 & ~HistoryItem.STATE2_WIFI_SUPPL_STATE_MASK)
- | (supplState << HistoryItem.STATE2_WIFI_SUPPL_STATE_SHIFT);
+ setBitField(mHistoryCur.states2, supplState,
+ HistoryItem.STATE2_WIFI_SUPPL_STATE_SHIFT,
+ HistoryItem.STATE2_WIFI_SUPPL_STATE_MASK);
writeHistoryItem(elapsedRealtimeMs, uptimeMs);
}
@@ -1168,8 +1171,9 @@
public void recordWifiSignalStrengthChangeEvent(long elapsedRealtimeMs, long uptimeMs,
int strengthBin) {
mHistoryCur.states2 =
- (mHistoryCur.states2 & ~HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_MASK)
- | (strengthBin << HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_SHIFT);
+ setBitField(mHistoryCur.states2, strengthBin,
+ HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_SHIFT,
+ HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_MASK);
writeHistoryItem(elapsedRealtimeMs, uptimeMs);
}
@@ -1227,6 +1231,16 @@
}
}
+ private int setBitField(int bits, int value, int shift, int mask) {
+ int shiftedValue = value << shift;
+ if ((shiftedValue & ~mask) != 0) {
+ Slog.wtfStack(TAG, "Value " + Integer.toHexString(value)
+ + " does not fit in the bit field: " + Integer.toHexString(mask));
+ shiftedValue &= mask;
+ }
+ return (bits & ~mask) | shiftedValue;
+ }
+
/**
* Writes the current history item to history.
*/
@@ -1260,8 +1274,8 @@
}
final long timeDiffMs = (mHistoryBaseTimeMs + elapsedRealtimeMs) - mHistoryLastWritten.time;
- final int diffStates = mHistoryLastWritten.states ^ (cur.states & mActiveHistoryStates);
- final int diffStates2 = mHistoryLastWritten.states2 ^ (cur.states2 & mActiveHistoryStates2);
+ final int diffStates = mHistoryLastWritten.states ^ cur.states;
+ final int diffStates2 = mHistoryLastWritten.states2 ^ cur.states2;
final int lastDiffStates = mHistoryLastWritten.states ^ mHistoryLastLastWritten.states;
final int lastDiffStates2 = mHistoryLastWritten.states2 ^ mHistoryLastLastWritten.states2;
if (DEBUG) {
@@ -1274,9 +1288,9 @@
recordTraceEvents(cur.eventCode, cur.eventTag);
recordTraceCounters(mHistoryLastWritten.states,
- cur.states & mActiveHistoryStates, BatteryStats.HISTORY_STATE_DESCRIPTIONS);
+ cur.states, BatteryStats.HISTORY_STATE_DESCRIPTIONS);
recordTraceCounters(mHistoryLastWritten.states2,
- cur.states2 & mActiveHistoryStates2, BatteryStats.HISTORY_STATE2_DESCRIPTIONS);
+ cur.states2, BatteryStats.HISTORY_STATE2_DESCRIPTIONS);
if (mHistoryBufferLastPos >= 0 && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE
&& timeDiffMs < 1000 && (diffStates & lastDiffStates) == 0
@@ -1387,8 +1401,6 @@
final boolean hasTags = mHistoryLastWritten.tagsFirstOccurrence || cur.tagsFirstOccurrence;
mHistoryLastWritten.setTo(mHistoryBaseTimeMs + elapsedRealtimeMs, cmd, cur);
mHistoryLastWritten.tagsFirstOccurrence = hasTags;
- mHistoryLastWritten.states &= mActiveHistoryStates;
- mHistoryLastWritten.states2 &= mActiveHistoryStates2;
writeHistoryDelta(mHistoryBuffer, mHistoryLastWritten, mHistoryLastLastWritten);
mLastHistoryElapsedRealtimeMs = elapsedRealtimeMs;
cur.wakelockTag = null;
@@ -1627,7 +1639,7 @@
}
if (cur.eventCode != HistoryItem.EVENT_NONE) {
final int index = writeHistoryTag(cur.eventTag);
- final int codeAndIndex = (cur.eventCode & 0xffff) | (index << 16);
+ final int codeAndIndex = setBitField(cur.eventCode & 0xffff, index, 16, 0xFFFF0000);
dest.writeInt(codeAndIndex);
if ((index & BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG) != 0) {
cur.eventTag.writeToParcel(dest, 0);
@@ -1689,9 +1701,11 @@
}
private int buildBatteryLevelInt(HistoryItem h) {
- return ((((int) h.batteryLevel) << 25) & 0xfe000000)
- | ((((int) h.batteryTemperature) << 15) & 0x01ff8000)
- | ((((int) h.batteryVoltage) << 1) & 0x00007ffe);
+ int bits = 0;
+ bits = setBitField(bits, h.batteryLevel, 25, 0xfe000000 /* 7F << 25 */);
+ bits = setBitField(bits, h.batteryTemperature, 15, 0x01ff8000 /* 3FF << 15 */);
+ bits = setBitField(bits, h.batteryVoltage, 1, 0x00007ffe /* 3FFF << 1 */);
+ return bits;
}
private int buildStateInt(HistoryItem h) {
diff --git a/core/java/com/android/internal/os/anr/AnrLatencyTracker.java b/core/java/com/android/internal/os/anr/AnrLatencyTracker.java
index 2748ded..6a61656 100644
--- a/core/java/com/android/internal/os/anr/AnrLatencyTracker.java
+++ b/core/java/com/android/internal/os/anr/AnrLatencyTracker.java
@@ -79,11 +79,11 @@
private int mAnrType;
private int mDumpedProcessesCount = 0;
- private long mFirstPidsDumpingStart;
+ private long mFirstPidsDumpingStartUptime;
private long mFirstPidsDumpingDuration = 0;
- private long mNativePidsDumpingStart;
+ private long mNativePidsDumpingStartUptime;
private long mNativePidsDumpingDuration = 0;
- private long mExtraPidsDumpingStart;
+ private long mExtraPidsDumpingStartUptime;
private long mExtraPidsDumpingDuration = 0;
private boolean mIsPushed = false;
@@ -223,37 +223,37 @@
/** Records the start of pid dumping to file (subject and criticalEventSection). */
public void dumpingFirstPidsStarted() {
- mFirstPidsDumpingStart = getUptimeMillis();
+ mFirstPidsDumpingStartUptime = getUptimeMillis();
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "dumpingFirstPids");
}
/** Records the end of pid dumping to file (subject and criticalEventSection). */
public void dumpingFirstPidsEnded() {
- mFirstPidsDumpingDuration = getUptimeMillis() - mFirstPidsDumpingStart;
+ mFirstPidsDumpingDuration = getUptimeMillis() - mFirstPidsDumpingStartUptime;
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
/** Records the start of pid dumping to file (subject and criticalEventSection). */
public void dumpingNativePidsStarted() {
- mNativePidsDumpingStart = getUptimeMillis();
+ mNativePidsDumpingStartUptime = getUptimeMillis();
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "dumpingNativePids");
}
/** Records the end of pid dumping to file (subject and criticalEventSection). */
public void dumpingNativePidsEnded() {
- mNativePidsDumpingDuration = getUptimeMillis() - mNativePidsDumpingStart;
+ mNativePidsDumpingDuration = getUptimeMillis() - mNativePidsDumpingStartUptime;
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
/** Records the start of pid dumping to file (subject and criticalEventSection). */
public void dumpingExtraPidsStarted() {
- mExtraPidsDumpingStart = getUptimeMillis();
+ mExtraPidsDumpingStartUptime = getUptimeMillis();
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "dumpingExtraPids");
}
/** Records the end of pid dumping to file (subject and criticalEventSection). */
public void dumpingExtraPidsEnded() {
- mExtraPidsDumpingDuration = getUptimeMillis() - mExtraPidsDumpingStart;
+ mExtraPidsDumpingDuration = getUptimeMillis() - mExtraPidsDumpingStartUptime;
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
@@ -337,7 +337,7 @@
* Returns latency data as a comma separated value string for inclusion in ANR report.
*/
public String dumpAsCommaSeparatedArrayWithHeader() {
- return "DurationsV1: " + mAnrTriggerUptime
+ return "DurationsV2: " + mAnrTriggerUptime
/* triggering_to_app_not_responding_duration = */
+ "," + (mAppNotRespondingStartUptime - mAnrTriggerUptime)
/* app_not_responding_duration = */
@@ -369,8 +369,8 @@
/* anr_queue_size_when_pushed = */
+ "," + mAnrQueueSize
- /* dumped_processes_count = */
- + "," + mDumpedProcessesCount
+ /* dump_stack_traces_io_time = */
+ + "," + (mFirstPidsDumpingStartUptime - mDumpStackTracesStartUptime)
+ "\n\n";
}
@@ -422,7 +422,7 @@
/* total_duration = */ mEndUptime - mAnrTriggerUptime,
/* triggering_to_stack_dump_duration = */
- mFirstPidsDumpingStart - mAnrTriggerUptime,
+ mFirstPidsDumpingStartUptime - mAnrTriggerUptime,
/* triggering_to_app_not_responding_duration = */
mAppNotRespondingStartUptime - mAnrTriggerUptime,
/* app_not_responding_duration = */
diff --git a/core/java/com/android/internal/os/anr/OWNERS b/core/java/com/android/internal/os/anr/OWNERS
new file mode 100644
index 0000000..9816752
--- /dev/null
+++ b/core/java/com/android/internal/os/anr/OWNERS
@@ -0,0 +1,3 @@
+benmiles@google.com
+gaillard@google.com
+mohamadmahmoud@google.com
\ No newline at end of file
diff --git a/core/java/com/android/internal/policy/TransitionAnimation.java b/core/java/com/android/internal/policy/TransitionAnimation.java
index 25ac1bd..600ae50 100644
--- a/core/java/com/android/internal/policy/TransitionAnimation.java
+++ b/core/java/com/android/internal/policy/TransitionAnimation.java
@@ -1279,10 +1279,15 @@
public static float getBorderLuma(SurfaceControl surfaceControl, int w, int h) {
final ScreenCapture.ScreenshotHardwareBuffer buffer =
ScreenCapture.captureLayers(surfaceControl, new Rect(0, 0, w, h), 1);
- if (buffer != null) {
- return getBorderLuma(buffer.getHardwareBuffer(), buffer.getColorSpace());
+ if (buffer == null) {
+ return 0;
}
- return 0;
+ final HardwareBuffer hwBuffer = buffer.getHardwareBuffer();
+ final float luma = getBorderLuma(hwBuffer, buffer.getColorSpace());
+ if (hwBuffer != null) {
+ hwBuffer.close();
+ }
+ return luma;
}
/** Returns the luminance in 0~1. */
diff --git a/core/java/com/android/internal/power/EnergyConsumerStats.java b/core/java/com/android/internal/power/EnergyConsumerStats.java
index 325df57..8cf17cda 100644
--- a/core/java/com/android/internal/power/EnergyConsumerStats.java
+++ b/core/java/com/android/internal/power/EnergyConsumerStats.java
@@ -58,7 +58,8 @@
public static final int POWER_BUCKET_BLUETOOTH = 5;
public static final int POWER_BUCKET_GNSS = 6;
public static final int POWER_BUCKET_MOBILE_RADIO = 7;
- public static final int NUMBER_STANDARD_POWER_BUCKETS = 8; // Buckets above this are custom.
+ public static final int POWER_BUCKET_CAMERA = 8;
+ public static final int NUMBER_STANDARD_POWER_BUCKETS = 9; // Buckets above this are custom.
@IntDef(prefix = {"POWER_BUCKET_"}, value = {
POWER_BUCKET_UNKNOWN,
@@ -70,6 +71,7 @@
POWER_BUCKET_BLUETOOTH,
POWER_BUCKET_GNSS,
POWER_BUCKET_MOBILE_RADIO,
+ POWER_BUCKET_CAMERA,
})
@Retention(RetentionPolicy.SOURCE)
public @interface StandardPowerBucket {
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index db288c0..8fb345b 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -53,7 +53,7 @@
boolean showImeSwitcher);
void setWindowState(int display, int window, int state);
- void showRecentApps(boolean triggeredFromAltTab);
+ void showRecentApps(boolean triggeredFromAltTab, boolean forward);
void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey);
void toggleRecentApps();
void toggleSplitScreen();
diff --git a/core/java/com/android/internal/util/LatencyTracker.java b/core/java/com/android/internal/util/LatencyTracker.java
index afb526a..2d5bb6c 100644
--- a/core/java/com/android/internal/util/LatencyTracker.java
+++ b/core/java/com/android/internal/util/LatencyTracker.java
@@ -14,7 +14,10 @@
package com.android.internal.util;
+import static android.Manifest.permission.READ_DEVICE_CONFIG;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.Trace.TRACE_TAG_APP;
+import static android.provider.DeviceConfig.NAMESPACE_LATENCY_TRACKER;
import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_CHECK_CREDENTIAL;
import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_CHECK_CREDENTIAL_UNLOCKED;
@@ -24,6 +27,8 @@
import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_FOLD_TO_AOD;
import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_LOAD_SHARE_SHEET;
import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_LOCKSCREEN_UNLOCK;
+import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_REQUEST_IME_HIDDEN;
+import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_REQUEST_IME_SHOWN;
import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_ROTATE_SCREEN;
import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_ROTATE_SCREEN_CAMERA_CHECK;
import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_ROTATE_SCREEN_SENSOR;
@@ -42,9 +47,12 @@
import static com.android.internal.util.LatencyTracker.ActionProperties.SAMPLE_INTERVAL_SUFFIX;
import static com.android.internal.util.LatencyTracker.ActionProperties.TRACE_THRESHOLD_SUFFIX;
+import android.Manifest;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.app.ActivityThread;
import android.content.Context;
import android.os.Build;
import android.os.ConditionVariable;
@@ -187,6 +195,16 @@
*/
public static final int ACTION_SHOW_VOICE_INTERACTION = 19;
+ /**
+ * Time it takes to request IME shown animation.
+ */
+ public static final int ACTION_REQUEST_IME_SHOWN = 20;
+
+ /**
+ * Time it takes to request IME hidden animation.
+ */
+ public static final int ACTION_REQUEST_IME_HIDDEN = 21;
+
private static final int[] ACTIONS_ALL = {
ACTION_EXPAND_PANEL,
ACTION_TOGGLE_RECENTS,
@@ -208,6 +226,8 @@
ACTION_SHOW_SELECTION_TOOLBAR,
ACTION_FOLD_TO_AOD,
ACTION_SHOW_VOICE_INTERACTION,
+ ACTION_REQUEST_IME_SHOWN,
+ ACTION_REQUEST_IME_HIDDEN,
};
/** @hide */
@@ -232,6 +252,8 @@
ACTION_SHOW_SELECTION_TOOLBAR,
ACTION_FOLD_TO_AOD,
ACTION_SHOW_VOICE_INTERACTION,
+ ACTION_REQUEST_IME_SHOWN,
+ ACTION_REQUEST_IME_HIDDEN,
})
@Retention(RetentionPolicy.SOURCE)
public @interface Action {
@@ -259,6 +281,8 @@
UIACTION_LATENCY_REPORTED__ACTION__ACTION_SHOW_SELECTION_TOOLBAR,
UIACTION_LATENCY_REPORTED__ACTION__ACTION_FOLD_TO_AOD,
UIACTION_LATENCY_REPORTED__ACTION__ACTION_SHOW_VOICE_INTERACTION,
+ UIACTION_LATENCY_REPORTED__ACTION__ACTION_REQUEST_IME_SHOWN,
+ UIACTION_LATENCY_REPORTED__ACTION__ACTION_REQUEST_IME_HIDDEN,
};
private static LatencyTracker sLatencyTracker;
@@ -284,15 +308,30 @@
return sLatencyTracker;
}
+ @RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
@VisibleForTesting
public LatencyTracker() {
mEnabled = DEFAULT_ENABLED;
- // Post initialization to the background in case we're running on the main thread.
- BackgroundThread.getHandler().post(() -> this.updateProperties(
- DeviceConfig.getProperties(DeviceConfig.NAMESPACE_LATENCY_TRACKER)));
- DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_LATENCY_TRACKER,
- BackgroundThread.getExecutor(), this::updateProperties);
+ final Context context = ActivityThread.currentApplication();
+ if (context != null
+ && context.checkCallingOrSelfPermission(READ_DEVICE_CONFIG) == PERMISSION_GRANTED) {
+ // Post initialization to the background in case we're running on the main thread.
+ BackgroundThread.getHandler().post(() -> this.updateProperties(
+ DeviceConfig.getProperties(NAMESPACE_LATENCY_TRACKER)));
+ DeviceConfig.addOnPropertiesChangedListener(NAMESPACE_LATENCY_TRACKER,
+ BackgroundThread.getExecutor(), this::updateProperties);
+ } else {
+ if (DEBUG) {
+ if (context == null) {
+ Log.d(TAG, "No application for " + ActivityThread.currentActivityThread());
+ } else {
+ Log.d(TAG, "Initialized the LatencyTracker."
+ + " (No READ_DEVICE_CONFIG permission to change configs)"
+ + " enabled=" + mEnabled + ", package=" + context.getPackageName());
+ }
+ }
+ }
}
private void updateProperties(DeviceConfig.Properties properties) {
@@ -368,6 +407,10 @@
return "ACTION_FOLD_TO_AOD";
case UIACTION_LATENCY_REPORTED__ACTION__ACTION_SHOW_VOICE_INTERACTION:
return "ACTION_SHOW_VOICE_INTERACTION";
+ case UIACTION_LATENCY_REPORTED__ACTION__ACTION_REQUEST_IME_SHOWN:
+ return "ACTION_REQUEST_IME_SHOWN";
+ case UIACTION_LATENCY_REPORTED__ACTION__ACTION_REQUEST_IME_HIDDEN:
+ return "ACTION_REQUEST_IME_HIDDEN";
default:
throw new IllegalArgumentException("Invalid action");
}
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index 2106426..9116cb3 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -40,6 +40,11 @@
// TODO: Use ParceledListSlice instead
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = "
+ "android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, conditional = true)")
+ InputMethodInfo getCurrentInputMethodInfoAsUser(int userId);
+
+ // TODO: Use ParceledListSlice instead
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = "
+ + "android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, conditional = true)")
List<InputMethodInfo> getInputMethodList(int userId, int directBootAwareness);
// TODO: Use ParceledListSlice instead
diff --git a/core/java/com/android/internal/view/inline/InlineTooltipUi.java b/core/java/com/android/internal/view/inline/InlineTooltipUi.java
index 836786d..7e12574 100644
--- a/core/java/com/android/internal/view/inline/InlineTooltipUi.java
+++ b/core/java/com/android/internal/view/inline/InlineTooltipUi.java
@@ -15,7 +15,7 @@
*/
package com.android.internal.view.inline;
-import static android.view.autofill.AutofillManager.DEVICE_CONFIG_AUTOFILL_TOOLTIP_SHOW_UP_DELAY;
+import static android.view.autofill.AutofillFeatureFlags.DEVICE_CONFIG_AUTOFILL_TOOLTIP_SHOW_UP_DELAY;
import static android.view.autofill.Helper.sVerbose;
import android.annotation.NonNull;
diff --git a/core/java/com/android/internal/widget/PointerLocationView.java b/core/java/com/android/internal/widget/PointerLocationView.java
index c08f264..f55d15d 100644
--- a/core/java/com/android/internal/widget/PointerLocationView.java
+++ b/core/java/com/android/internal/widget/PointerLocationView.java
@@ -92,12 +92,6 @@
private float mBoundingRight;
private float mBoundingBottom;
- // Position estimator.
- private VelocityTracker.Estimator mEstimatorX = new VelocityTracker.Estimator();
- private VelocityTracker.Estimator mAltEstimatorX = new VelocityTracker.Estimator();
- private VelocityTracker.Estimator mEstimatorY = new VelocityTracker.Estimator();
- private VelocityTracker.Estimator mAltEstimatorY = new VelocityTracker.Estimator();
-
@UnsupportedAppUsage
public PointerState() {
}
@@ -669,13 +663,9 @@
ps.addTrace(coords.x, coords.y, true);
ps.mXVelocity = mVelocity.getXVelocity(id);
ps.mYVelocity = mVelocity.getYVelocity(id);
- mVelocity.getEstimator(MotionEvent.AXIS_X, id, ps.mEstimatorX);
- mVelocity.getEstimator(MotionEvent.AXIS_Y, id, ps.mEstimatorY);
if (mAltVelocity != null) {
ps.mAltXVelocity = mAltVelocity.getXVelocity(id);
ps.mAltYVelocity = mAltVelocity.getYVelocity(id);
- mAltVelocity.getEstimator(MotionEvent.AXIS_X, id, ps.mAltEstimatorX);
- mAltVelocity.getEstimator(MotionEvent.AXIS_Y, id, ps.mAltEstimatorY);
}
ps.mToolType = event.getToolType(i);
diff --git a/core/java/com/android/server/backup/AccountManagerBackupHelper.java b/core/java/com/android/server/backup/AccountManagerBackupHelper.java
index f76dd09..5677699 100644
--- a/core/java/com/android/server/backup/AccountManagerBackupHelper.java
+++ b/core/java/com/android/server/backup/AccountManagerBackupHelper.java
@@ -18,8 +18,8 @@
import android.accounts.AccountManagerInternal;
import android.app.backup.BlobBackupHelper;
-import android.os.UserHandle;
import android.util.Slog;
+
import com.android.server.LocalServices;
/**
@@ -35,8 +35,11 @@
// key under which the account access grant state blob is committed to backup
private static final String KEY_ACCOUNT_ACCESS_GRANTS = "account_access_grants";
- public AccountManagerBackupHelper() {
+ private final int mUserId;
+
+ public AccountManagerBackupHelper(int userId) {
super(STATE_VERSION, KEY_ACCOUNT_ACCESS_GRANTS);
+ mUserId = userId;
}
@Override
@@ -48,7 +51,7 @@
try {
switch (key) {
case KEY_ACCOUNT_ACCESS_GRANTS: {
- return am.backupAccountAccessPermissions(UserHandle.USER_SYSTEM);
+ return am.backupAccountAccessPermissions(mUserId);
}
default: {
@@ -71,7 +74,7 @@
try {
switch (key) {
case KEY_ACCOUNT_ACCESS_GRANTS: {
- am.restoreAccountAccessPermissions(payload, UserHandle.USER_SYSTEM);
+ am.restoreAccountAccessPermissions(payload, mUserId);
} break;
default: {
diff --git a/core/java/com/android/server/backup/OWNERS b/core/java/com/android/server/backup/OWNERS
new file mode 100644
index 0000000..d99779e
--- /dev/null
+++ b/core/java/com/android/server/backup/OWNERS
@@ -0,0 +1 @@
+include /services/backup/OWNERS
diff --git a/core/jni/OWNERS b/core/jni/OWNERS
index 53594e1..a68040d 100644
--- a/core/jni/OWNERS
+++ b/core/jni/OWNERS
@@ -17,7 +17,9 @@
per-file android_view_KeyCharacterMap.* = file:/services/core/java/com/android/server/input/OWNERS
per-file android_view_*KeyEvent.* = file:/services/core/java/com/android/server/input/OWNERS
per-file android_view_*MotionEvent.* = file:/services/core/java/com/android/server/input/OWNERS
+per-file android_view_MotionPredictor.* = file:/services/core/java/com/android/server/input/OWNERS
per-file android_view_PointerIcon.* = file:/services/core/java/com/android/server/input/OWNERS
+per-file android_view_VelocityTracker.* = file:/services/core/java/com/android/server/input/OWNERS
# WindowManager
per-file android_graphics_BLASTBufferQueue.cpp = file:/services/core/java/com/android/server/wm/OWNERS
diff --git a/core/jni/android/opengl/util.cpp b/core/jni/android/opengl/util.cpp
index 17cfbfc..3b409d4 100644
--- a/core/jni/android/opengl/util.cpp
+++ b/core/jni/android/opengl/util.cpp
@@ -541,87 +541,6 @@
indices.mData, indexCount);
}
-#define I(_i, _j) ((_j)+ 4*(_i))
-
-static
-void multiplyMM(float* r, const float* lhs, const float* rhs)
-{
- for (int i=0 ; i<4 ; i++) {
- const float rhs_i0 = rhs[ I(i,0) ];
- float ri0 = lhs[ I(0,0) ] * rhs_i0;
- float ri1 = lhs[ I(0,1) ] * rhs_i0;
- float ri2 = lhs[ I(0,2) ] * rhs_i0;
- float ri3 = lhs[ I(0,3) ] * rhs_i0;
- for (int j=1 ; j<4 ; j++) {
- const float rhs_ij = rhs[ I(i,j) ];
- ri0 += lhs[ I(j,0) ] * rhs_ij;
- ri1 += lhs[ I(j,1) ] * rhs_ij;
- ri2 += lhs[ I(j,2) ] * rhs_ij;
- ri3 += lhs[ I(j,3) ] * rhs_ij;
- }
- r[ I(i,0) ] = ri0;
- r[ I(i,1) ] = ri1;
- r[ I(i,2) ] = ri2;
- r[ I(i,3) ] = ri3;
- }
-}
-
-static
-void util_multiplyMM(JNIEnv *env, jclass clazz,
- jfloatArray result_ref, jint resultOffset,
- jfloatArray lhs_ref, jint lhsOffset,
- jfloatArray rhs_ref, jint rhsOffset) {
-
- FloatArrayHelper resultMat(env, result_ref, resultOffset, 16);
- FloatArrayHelper lhs(env, lhs_ref, lhsOffset, 16);
- FloatArrayHelper rhs(env, rhs_ref, rhsOffset, 16);
-
- bool checkOK = resultMat.check() && lhs.check() && rhs.check();
-
- if ( !checkOK ) {
- return;
- }
-
- resultMat.bind();
- lhs.bind();
- rhs.bind();
-
- multiplyMM(resultMat.mData, lhs.mData, rhs.mData);
-
- resultMat.commitChanges();
-}
-
-static
-void multiplyMV(float* r, const float* lhs, const float* rhs)
-{
- mx4transform(rhs[0], rhs[1], rhs[2], rhs[3], lhs, r);
-}
-
-static
-void util_multiplyMV(JNIEnv *env, jclass clazz,
- jfloatArray result_ref, jint resultOffset,
- jfloatArray lhs_ref, jint lhsOffset,
- jfloatArray rhs_ref, jint rhsOffset) {
-
- FloatArrayHelper resultV(env, result_ref, resultOffset, 4);
- FloatArrayHelper lhs(env, lhs_ref, lhsOffset, 16);
- FloatArrayHelper rhs(env, rhs_ref, rhsOffset, 4);
-
- bool checkOK = resultV.check() && lhs.check() && rhs.check();
-
- if ( !checkOK ) {
- return;
- }
-
- resultV.bind();
- lhs.bind();
- rhs.bind();
-
- multiplyMV(resultV.mData, lhs.mData, rhs.mData);
-
- resultV.commitChanges();
-}
-
// ---------------------------------------------------------------------------
// The internal format is no longer the same as pixel format, per Table 2 in
@@ -1014,11 +933,6 @@
* JNI registration
*/
-static const JNINativeMethod gMatrixMethods[] = {
- { "multiplyMM", "([FI[FI[FI)V", (void*)util_multiplyMM },
- { "multiplyMV", "([FI[FI[FI)V", (void*)util_multiplyMV },
-};
-
static const JNINativeMethod gVisibilityMethods[] = {
{ "computeBoundingSphere", "([FII[FI)V", (void*)util_computeBoundingSphere },
{ "frustumCullSpheres", "([FI[FII[III)I", (void*)util_frustumCullSpheres },
@@ -1051,7 +965,6 @@
} ClassRegistrationInfo;
static const ClassRegistrationInfo gClasses[] = {
- {"android/opengl/Matrix", gMatrixMethods, NELEM(gMatrixMethods)},
{"android/opengl/Visibility", gVisibilityMethods, NELEM(gVisibilityMethods)},
{"android/opengl/GLUtils", gUtilsMethods, NELEM(gUtilsMethods)},
{"android/opengl/ETC1", gEtc1Methods, NELEM(gEtc1Methods)},
diff --git a/core/jni/android_view_VelocityTracker.cpp b/core/jni/android_view_VelocityTracker.cpp
index 343e9d8..05c9f68 100644
--- a/core/jni/android_view_VelocityTracker.cpp
+++ b/core/jni/android_view_VelocityTracker.cpp
@@ -31,13 +31,6 @@
// Special constant to request the velocity of the active pointer.
static const int ACTIVE_POINTER_ID = -1;
-static struct {
- jfieldID coeff;
- jfieldID degree;
- jfieldID confidence;
-} gEstimatorClassInfo;
-
-
// --- VelocityTrackerState ---
class VelocityTrackerState {
@@ -50,7 +43,6 @@
// a subset of the supported axes.
void computeCurrentVelocity(int32_t units, float maxVelocity);
float getVelocity(int32_t axis, int32_t id);
- bool getEstimator(int32_t axis, int32_t id, VelocityTracker::Estimator* outEstimator);
private:
VelocityTracker mVelocityTracker;
@@ -80,11 +72,6 @@
return mComputedVelocity.getVelocity(axis, id).value_or(0);
}
-bool VelocityTrackerState::getEstimator(int32_t axis, int32_t id,
- VelocityTracker::Estimator* outEstimator) {
- return mVelocityTracker.getEstimator(axis, id, outEstimator);
-}
-
// Return a strategy enum from integer value.
inline static VelocityTracker::Strategy getStrategyFromInt(const int32_t strategy) {
if (strategy < static_cast<int32_t>(VelocityTracker::Strategy::MIN) ||
@@ -135,24 +122,6 @@
return state->getVelocity(axis, id);
}
-static jboolean android_view_VelocityTracker_nativeGetEstimator(JNIEnv* env, jclass clazz,
- jlong ptr, jint axis, jint id,
- jobject outEstimatorObj) {
- VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
- VelocityTracker::Estimator estimator;
-
- bool result = state->getEstimator(axis, id, &estimator);
-
- jfloatArray coeffObj =
- jfloatArray(env->GetObjectField(outEstimatorObj, gEstimatorClassInfo.coeff));
-
- env->SetFloatArrayRegion(coeffObj, 0, VelocityTracker::Estimator::MAX_DEGREE + 1,
- estimator.coeff);
- env->SetIntField(outEstimatorObj, gEstimatorClassInfo.degree, estimator.degree);
- env->SetFloatField(outEstimatorObj, gEstimatorClassInfo.confidence, estimator.confidence);
- return result;
-}
-
static jboolean android_view_VelocityTracker_nativeIsAxisSupported(JNIEnv* env, jclass clazz,
jint axis) {
return VelocityTracker::isAxisSupported(axis);
@@ -170,23 +139,13 @@
{"nativeComputeCurrentVelocity", "(JIF)V",
(void*)android_view_VelocityTracker_nativeComputeCurrentVelocity},
{"nativeGetVelocity", "(JII)F", (void*)android_view_VelocityTracker_nativeGetVelocity},
- {"nativeGetEstimator", "(JIILandroid/view/VelocityTracker$Estimator;)Z",
- (void*)android_view_VelocityTracker_nativeGetEstimator},
{"nativeIsAxisSupported", "(I)Z",
(void*)android_view_VelocityTracker_nativeIsAxisSupported},
};
int register_android_view_VelocityTracker(JNIEnv* env) {
- int res = RegisterMethodsOrDie(env, "android/view/VelocityTracker", gVelocityTrackerMethods,
- NELEM(gVelocityTrackerMethods));
-
- jclass clazz = FindClassOrDie(env, "android/view/VelocityTracker$Estimator");
-
- gEstimatorClassInfo.coeff = GetFieldIDOrDie(env, clazz, "coeff", "[F");
- gEstimatorClassInfo.degree = GetFieldIDOrDie(env, clazz, "degree", "I");
- gEstimatorClassInfo.confidence = GetFieldIDOrDie(env, clazz, "confidence", "F");
-
- return res;
+ return RegisterMethodsOrDie(env, "android/view/VelocityTracker", gVelocityTrackerMethods,
+ NELEM(gVelocityTrackerMethods));
}
} // namespace android
diff --git a/core/proto/android/nfc/nfc_service.proto b/core/proto/android/nfc/nfc_service.proto
index 2df1d5d..1dcd5cc 100644
--- a/core/proto/android/nfc/nfc_service.proto
+++ b/core/proto/android/nfc/nfc_service.proto
@@ -60,7 +60,7 @@
optional bool secure_nfc_capable = 13;
optional bool vr_mode_enabled = 14;
optional DiscoveryParamsProto discovery_params = 15;
- optional P2pLinkManagerProto p2p_link_manager = 16;
+ reserved 16;
optional com.android.nfc.cardemulation.CardEmulationManagerProto card_emulation_manager = 17;
optional NfcDispatcherProto nfc_dispatcher = 18;
optional string native_crash_logs = 19 [(.android.privacy).dest = DEST_EXPLICIT];
@@ -77,38 +77,6 @@
optional bool enable_p2p = 5;
}
-// Debugging information for com.android.nfc.P2pLinkManager
-message P2pLinkManagerProto {
- option (.android.msg_privacy).dest = DEST_AUTOMATIC;
-
- enum LinkState {
- LINK_STATE_UNKNOWN = 0;
- LINK_STATE_DOWN = 1;
- LINK_STATE_DEBOUNCE = 2;
- LINK_STATE_UP = 3;
- }
-
- enum SendState {
- SEND_STATE_UNKNOWN = 0;
- SEND_STATE_NOTHING_TO_SEND = 1;
- SEND_STATE_NEED_CONFIRMATION = 2;
- SEND_STATE_SENDING = 3;
- SEND_STATE_COMPLETE = 4;
- SEND_STATE_CANCELED = 5;
- }
-
- optional int32 default_miu = 1;
- optional int32 default_rw_size = 2;
- optional LinkState link_state = 3;
- optional SendState send_state = 4;
- optional int32 send_flags = 5;
- optional bool send_enabled = 6;
- optional bool receive_enabled = 7;
- optional string callback_ndef = 8 [(.android.privacy).dest = DEST_EXPLICIT];
- optional .android.nfc.NdefMessageProto message_to_send = 9;
- repeated string uris_to_send = 10 [(.android.privacy).dest = DEST_EXPLICIT];
-}
-
// Debugging information for com.android.nfc.NfcDispatcher
message NfcDispatcherProto {
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
diff --git a/core/proto/android/server/inputmethod/inputmethodmanagerservice.proto b/core/proto/android/server/inputmethod/inputmethodmanagerservice.proto
index 35aae8f..5a18d9e 100644
--- a/core/proto/android/server/inputmethod/inputmethodmanagerservice.proto
+++ b/core/proto/android/server/inputmethod/inputmethodmanagerservice.proto
@@ -31,7 +31,7 @@
optional string cur_focused_window_soft_input_mode = 6;
optional .android.view.inputmethod.EditorInfoProto cur_attribute = 7;
optional string cur_id = 8;
- optional bool show_requested = 9;
+ reserved 9; // deprecated show_requested
optional bool show_explicitly_requested = 10;
optional bool show_forced = 11;
optional bool input_shown = 12;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 3fdd6c4..c052cca 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -4471,13 +4471,22 @@
<permission android:name="android.permission.BIND_HOTWORD_DETECTION_SERVICE"
android:protectionLevel="signature" />
- <!-- @SystemApi Allows an application to manage hotword detection on the device.
+ <!-- @SystemApi Allows an application to manage hotword detection and visual query detection
+ on the device.
<p>Protection level: internal|preinstalled
@hide This is not a third-party API (intended for OEMs and system apps).
-->
<permission android:name="android.permission.MANAGE_HOTWORD_DETECTION"
android:protectionLevel="internal|preinstalled" />
+ <!-- @SystemApi Must be required by a {@link android.service.voice.VisualQueryDetectionService},
+ to ensure that only the system can bind to it.
+ <p>Protection level: signature
+ @hide This is not a third-party API (intended for OEMs and system apps).
+ -->
+ <permission android:name="android.permission.BIND_VISUAL_QUERY_DETECTION_SERVICE"
+ android:protectionLevel="signature" />
+
<!-- Allows an application to subscribe to keyguard locked (i.e., showing) state.
<p>Protection level: internal|role
<p>Intended for use by ROLE_ASSISTANT only.
@@ -6862,6 +6871,15 @@
<permission android:name="android.permission.READ_HOME_APP_SEARCH_DATA"
android:protectionLevel="internal|role" />
+ <!-- Allows an assistive application to perform actions on behalf of users inside of
+ applications.
+ <p>For now, this permission is only granted to system applications fulfilling the
+ ASSISTANT role.
+ <p>Protection level: internal|role
+ -->
+ <permission android:name="android.permission.EXECUTE_APP_ACTION"
+ android:protectionLevel="internal|role" />
+
<!-- @SystemApi Allows an application to create virtual devices in VirtualDeviceManager.
@hide -->
<permission android:name="android.permission.CREATE_VIRTUAL_DEVICE"
@@ -6907,7 +6925,7 @@
@hide
-->
<permission android:name="android.permission.ACCESS_AMBIENT_CONTEXT_EVENT"
- android:protectionLevel="internal|role"/>
+ android:protectionLevel="signature|privileged|role"/>
<!-- @SystemApi Required by a AmbientContextEventDetectionService
to ensure that only the service with this permission can bind to it.
@@ -6994,14 +7012,12 @@
<permission android:name="android.permission.MANAGE_WEARABLE_SENSING_SERVICE"
android:protectionLevel="signature|privileged" />
- <!-- Allows applications to use the long running jobs APIs.
- <p>This is a special access permission that can be revoked by the system or the user.
- <p>Apps need to target API {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} or above
- to be able to request this permission.
- <p>Protection level: appop
+ <!-- Allows applications to use the long running jobs APIs. For more details
+ see {@link android.app.job.JobInfo.Builder#setUserInitiated}.
+ <p>Protection level: normal
-->
<permission android:name="android.permission.RUN_LONG_JOBS"
- android:protectionLevel="normal|appop"/>
+ android:protectionLevel="normal"/>
<!-- Allows an app access to the installer provided app metadata.
@SystemApi
@@ -7578,7 +7594,7 @@
</intent-filter>
</service>
- <service android:name="com.android.server.art.BackgroundDexOptJobService"
+ <service android:name="com.android.server.art.BackgroundDexoptJobService"
android:permission="android.permission.BIND_JOB_SERVICE" >
</service>
diff --git a/core/res/OWNERS b/core/res/OWNERS
index b878189..bce500c 100644
--- a/core/res/OWNERS
+++ b/core/res/OWNERS
@@ -23,8 +23,8 @@
# WindowManager team
# TODO(262451702): Move WindowManager configs out of config.xml in a separate file
-per-file core/res/res/values/config.xml = file:/services/core/java/com/android/server/wm/OWNERS
-per-file core/res/res/values/symbols.xml = file:/services/core/java/com/android/server/wm/OWNERS
+per-file res/values/config.xml = file:/services/core/java/com/android/server/wm/OWNERS
+per-file res/values/symbols.xml = file:/services/core/java/com/android/server/wm/OWNERS
# Resources finalization
per-file res/xml/public-staging.xml = file:/tools/aapt2/OWNERS
diff --git a/core/res/res/drawable-en-hdpi/sym_keyboard_delete.png b/core/res/res/drawable-en-hdpi/sym_keyboard_delete.png
index 569369e..6e08d80 100644
--- a/core/res/res/drawable-en-hdpi/sym_keyboard_delete.png
+++ b/core/res/res/drawable-en-hdpi/sym_keyboard_delete.png
Binary files differ
diff --git a/core/res/res/drawable-en-ldpi/sym_keyboard_delete.png b/core/res/res/drawable-en-ldpi/sym_keyboard_delete.png
index d9d5653..87aec1d 100644
--- a/core/res/res/drawable-en-ldpi/sym_keyboard_delete.png
+++ b/core/res/res/drawable-en-ldpi/sym_keyboard_delete.png
Binary files differ
diff --git a/core/res/res/drawable-en-ldpi/sym_keyboard_feedback_delete.png b/core/res/res/drawable-en-ldpi/sym_keyboard_feedback_delete.png
index 8922bf9..2d689c9 100644
--- a/core/res/res/drawable-en-ldpi/sym_keyboard_feedback_delete.png
+++ b/core/res/res/drawable-en-ldpi/sym_keyboard_feedback_delete.png
Binary files differ
diff --git a/core/res/res/drawable-en-mdpi/sym_keyboard_delete.png b/core/res/res/drawable-en-mdpi/sym_keyboard_delete.png
index f1f7c58c..e3a1fbe 100644
--- a/core/res/res/drawable-en-mdpi/sym_keyboard_delete.png
+++ b/core/res/res/drawable-en-mdpi/sym_keyboard_delete.png
Binary files differ
diff --git a/core/res/res/drawable-en-mdpi/sym_keyboard_feedback_delete.png b/core/res/res/drawable-en-mdpi/sym_keyboard_feedback_delete.png
index 3c90839..cf7f26aa 100644
--- a/core/res/res/drawable-en-mdpi/sym_keyboard_feedback_delete.png
+++ b/core/res/res/drawable-en-mdpi/sym_keyboard_feedback_delete.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_bottom_solid_dark_holo.9.png b/core/res/res/drawable-hdpi/ab_bottom_solid_dark_holo.9.png
index 769463b..f203bb0 100644
--- a/core/res/res/drawable-hdpi/ab_bottom_solid_dark_holo.9.png
+++ b/core/res/res/drawable-hdpi/ab_bottom_solid_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_bottom_solid_inverse_holo.9.png b/core/res/res/drawable-hdpi/ab_bottom_solid_inverse_holo.9.png
index 88f11dc..7900f68 100644
--- a/core/res/res/drawable-hdpi/ab_bottom_solid_inverse_holo.9.png
+++ b/core/res/res/drawable-hdpi/ab_bottom_solid_inverse_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_bottom_solid_light_holo.9.png b/core/res/res/drawable-hdpi/ab_bottom_solid_light_holo.9.png
index 7305047..eb38a36 100644
--- a/core/res/res/drawable-hdpi/ab_bottom_solid_light_holo.9.png
+++ b/core/res/res/drawable-hdpi/ab_bottom_solid_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_bottom_transparent_dark_holo.9.png b/core/res/res/drawable-hdpi/ab_bottom_transparent_dark_holo.9.png
index 712a551..486e0a4 100644
--- a/core/res/res/drawable-hdpi/ab_bottom_transparent_dark_holo.9.png
+++ b/core/res/res/drawable-hdpi/ab_bottom_transparent_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_bottom_transparent_light_holo.9.png b/core/res/res/drawable-hdpi/ab_bottom_transparent_light_holo.9.png
index bf3b943..0b0ce79 100644
--- a/core/res/res/drawable-hdpi/ab_bottom_transparent_light_holo.9.png
+++ b/core/res/res/drawable-hdpi/ab_bottom_transparent_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_share_pack_holo_dark.9.png b/core/res/res/drawable-hdpi/ab_share_pack_holo_dark.9.png
index 6c14157..05678cf 100644
--- a/core/res/res/drawable-hdpi/ab_share_pack_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/ab_share_pack_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_share_pack_holo_light.9.png b/core/res/res/drawable-hdpi/ab_share_pack_holo_light.9.png
index f4ff16b..023e706 100644
--- a/core/res/res/drawable-hdpi/ab_share_pack_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/ab_share_pack_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_share_pack_mtrl_alpha.9.png b/core/res/res/drawable-hdpi/ab_share_pack_mtrl_alpha.9.png
index b07da0c..5bb7d1b 100644
--- a/core/res/res/drawable-hdpi/ab_share_pack_mtrl_alpha.9.png
+++ b/core/res/res/drawable-hdpi/ab_share_pack_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_solid_dark_holo.9.png b/core/res/res/drawable-hdpi/ab_solid_dark_holo.9.png
index cbbaec5..54d033c 100644
--- a/core/res/res/drawable-hdpi/ab_solid_dark_holo.9.png
+++ b/core/res/res/drawable-hdpi/ab_solid_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_solid_light_holo.9.png b/core/res/res/drawable-hdpi/ab_solid_light_holo.9.png
index af917e5..18e9c83 100644
--- a/core/res/res/drawable-hdpi/ab_solid_light_holo.9.png
+++ b/core/res/res/drawable-hdpi/ab_solid_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_solid_shadow_holo.9.png b/core/res/res/drawable-hdpi/ab_solid_shadow_holo.9.png
index 2d59f35..5a65fae 100644
--- a/core/res/res/drawable-hdpi/ab_solid_shadow_holo.9.png
+++ b/core/res/res/drawable-hdpi/ab_solid_shadow_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_solid_shadow_mtrl_alpha.9.png b/core/res/res/drawable-hdpi/ab_solid_shadow_mtrl_alpha.9.png
index e49ad54..9bf1c57 100644
--- a/core/res/res/drawable-hdpi/ab_solid_shadow_mtrl_alpha.9.png
+++ b/core/res/res/drawable-hdpi/ab_solid_shadow_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_stacked_solid_dark_holo.9.png b/core/res/res/drawable-hdpi/ab_stacked_solid_dark_holo.9.png
index 0520e5a..c1b7dc0 100644
--- a/core/res/res/drawable-hdpi/ab_stacked_solid_dark_holo.9.png
+++ b/core/res/res/drawable-hdpi/ab_stacked_solid_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_stacked_solid_inverse_holo.9.png b/core/res/res/drawable-hdpi/ab_stacked_solid_inverse_holo.9.png
index 42528b1..0f7ee3b 100644
--- a/core/res/res/drawable-hdpi/ab_stacked_solid_inverse_holo.9.png
+++ b/core/res/res/drawable-hdpi/ab_stacked_solid_inverse_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_stacked_solid_light_holo.9.png b/core/res/res/drawable-hdpi/ab_stacked_solid_light_holo.9.png
index e3e3f93..7416746 100644
--- a/core/res/res/drawable-hdpi/ab_stacked_solid_light_holo.9.png
+++ b/core/res/res/drawable-hdpi/ab_stacked_solid_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_stacked_transparent_dark_holo.9.png b/core/res/res/drawable-hdpi/ab_stacked_transparent_dark_holo.9.png
index 1e39572..c9fc6f3 100644
--- a/core/res/res/drawable-hdpi/ab_stacked_transparent_dark_holo.9.png
+++ b/core/res/res/drawable-hdpi/ab_stacked_transparent_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_stacked_transparent_light_holo.9.png b/core/res/res/drawable-hdpi/ab_stacked_transparent_light_holo.9.png
index a16db85..0e8d650 100644
--- a/core/res/res/drawable-hdpi/ab_stacked_transparent_light_holo.9.png
+++ b/core/res/res/drawable-hdpi/ab_stacked_transparent_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_transparent_dark_holo.9.png b/core/res/res/drawable-hdpi/ab_transparent_dark_holo.9.png
index 0eff695..04b9c04 100644
--- a/core/res/res/drawable-hdpi/ab_transparent_dark_holo.9.png
+++ b/core/res/res/drawable-hdpi/ab_transparent_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_transparent_light_holo.9.png b/core/res/res/drawable-hdpi/ab_transparent_light_holo.9.png
index 219b170..d4d19f6 100644
--- a/core/res/res/drawable-hdpi/ab_transparent_light_holo.9.png
+++ b/core/res/res/drawable-hdpi/ab_transparent_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/activity_title_bar.9.png b/core/res/res/drawable-hdpi/activity_title_bar.9.png
index 48d60c4..a2c92b2 100644
--- a/core/res/res/drawable-hdpi/activity_title_bar.9.png
+++ b/core/res/res/drawable-hdpi/activity_title_bar.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/arrow_down_float.png b/core/res/res/drawable-hdpi/arrow_down_float.png
index 2466c8f..3442605 100644
--- a/core/res/res/drawable-hdpi/arrow_down_float.png
+++ b/core/res/res/drawable-hdpi/arrow_down_float.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/arrow_up_float.png b/core/res/res/drawable-hdpi/arrow_up_float.png
index d1301c3..b2b1bcb 100644
--- a/core/res/res/drawable-hdpi/arrow_up_float.png
+++ b/core/res/res/drawable-hdpi/arrow_up_float.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/battery_charge_background.png b/core/res/res/drawable-hdpi/battery_charge_background.png
index 19023a9..6c3f503 100644
--- a/core/res/res/drawable-hdpi/battery_charge_background.png
+++ b/core/res/res/drawable-hdpi/battery_charge_background.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/bottom_bar.png b/core/res/res/drawable-hdpi/bottom_bar.png
index 1f38f3c..74ff9af 100644
--- a/core/res/res/drawable-hdpi/bottom_bar.png
+++ b/core/res/res/drawable-hdpi/bottom_bar.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_cab_done_default_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_cab_done_default_holo_dark.9.png
index b0dc31f..dc11d58 100644
--- a/core/res/res/drawable-hdpi/btn_cab_done_default_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_cab_done_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_cab_done_default_holo_light.9.png b/core/res/res/drawable-hdpi/btn_cab_done_default_holo_light.9.png
index 4bc2683..44d3d0c 100644
--- a/core/res/res/drawable-hdpi/btn_cab_done_default_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_cab_done_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_cab_done_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_cab_done_focused_holo_dark.9.png
index 4af38fb..428ab0ac 100644
--- a/core/res/res/drawable-hdpi/btn_cab_done_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_cab_done_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_cab_done_focused_holo_light.9.png b/core/res/res/drawable-hdpi/btn_cab_done_focused_holo_light.9.png
index d32f74c..0194c21 100644
--- a/core/res/res/drawable-hdpi/btn_cab_done_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_cab_done_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_cab_done_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_cab_done_pressed_holo_dark.9.png
index 99d60e3..f9a4bd8 100644
--- a/core/res/res/drawable-hdpi/btn_cab_done_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_cab_done_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_cab_done_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/btn_cab_done_pressed_holo_light.9.png
index 45a0cf0..3a024a1 100644
--- a/core/res/res/drawable-hdpi/btn_cab_done_pressed_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_cab_done_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_buttonless_off.png b/core/res/res/drawable-hdpi/btn_check_buttonless_off.png
index baf9010..d3c8e85 100644
--- a/core/res/res/drawable-hdpi/btn_check_buttonless_off.png
+++ b/core/res/res/drawable-hdpi/btn_check_buttonless_off.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_buttonless_on.png b/core/res/res/drawable-hdpi/btn_check_buttonless_on.png
index 2a77e4c..de3a88c 100644
--- a/core/res/res/drawable-hdpi/btn_check_buttonless_on.png
+++ b/core/res/res/drawable-hdpi/btn_check_buttonless_on.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_label_background.9.png b/core/res/res/drawable-hdpi/btn_check_label_background.9.png
index 97e6806..ab34190 100644
--- a/core/res/res/drawable-hdpi/btn_check_label_background.9.png
+++ b/core/res/res/drawable-hdpi/btn_check_label_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off.png b/core/res/res/drawable-hdpi/btn_check_off.png
index 3928b7df..4a0405e 100644
--- a/core/res/res/drawable-hdpi/btn_check_off.png
+++ b/core/res/res/drawable-hdpi/btn_check_off.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_disable.png b/core/res/res/drawable-hdpi/btn_check_off_disable.png
index 922737e..754d4bf 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_disable.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_disable.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_disable_focused.png b/core/res/res/drawable-hdpi/btn_check_off_disable_focused.png
index 992f0fe..6a51ec1 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_disable_focused.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_disable_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_off_disable_focused_holo_dark.png
index d93e580..af38e64 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_disable_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_disable_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_disable_focused_holo_light.png b/core/res/res/drawable-hdpi/btn_check_off_disable_focused_holo_light.png
index ffbe776..8f6ad7a 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_disable_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_disable_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_disable_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_off_disable_holo_dark.png
index d93e580..af38e64 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_disable_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_disable_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_disable_holo_light.png b/core/res/res/drawable-hdpi/btn_check_off_disable_holo_light.png
index ffbe776..8f6ad7a 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_disable_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_disable_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_disabled_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_off_disabled_focused_holo_dark.png
index 50908bd..023b136 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_disabled_focused_holo_light.png b/core/res/res/drawable-hdpi/btn_check_off_disabled_focused_holo_light.png
index 64c3b9b..d6d7a52 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_disabled_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_off_disabled_holo_dark.png
index 4bcc51d..2f01603 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_disabled_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_disabled_holo_light.png b/core/res/res/drawable-hdpi/btn_check_off_disabled_holo_light.png
index 9dbad9b..219ac77 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_disabled_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_off_focused_holo_dark.png
index 2d5b328..c93819f 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_focused_holo_light.png b/core/res/res/drawable-hdpi/btn_check_off_focused_holo_light.png
index e1474f0..88ad32d 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_holo.png b/core/res/res/drawable-hdpi/btn_check_off_holo.png
index 9a5d158..a7d802b 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_holo.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_off_holo_dark.png
index d141b28..820ce21 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_holo_light.png b/core/res/res/drawable-hdpi/btn_check_off_holo_light.png
index 696810e..e8b12e8 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_normal_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_off_normal_holo_dark.png
index b81d4f9..06b686e 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_normal_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_normal_holo_light.png b/core/res/res/drawable-hdpi/btn_check_off_normal_holo_light.png
index b74055e..f9e6ccf 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_normal_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_pressed.png b/core/res/res/drawable-hdpi/btn_check_off_pressed.png
index c6195ab..3a46c5a 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_pressed.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_pressed_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_off_pressed_holo_dark.png
index 86b43c1..509055a 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_pressed_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_pressed_holo_light.png b/core/res/res/drawable-hdpi/btn_check_off_pressed_holo_light.png
index cdf0078..64c36c8 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_pressed_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_selected.png b/core/res/res/drawable-hdpi/btn_check_off_selected.png
index d467769..d537602 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_selected.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_selected.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on.png b/core/res/res/drawable-hdpi/btn_check_on.png
index 91d8ba9..00571f5 100644
--- a/core/res/res/drawable-hdpi/btn_check_on.png
+++ b/core/res/res/drawable-hdpi/btn_check_on.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_disable.png b/core/res/res/drawable-hdpi/btn_check_on_disable.png
index 6472087..bdb6c6f 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_disable.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_disable.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_disable_focused.png b/core/res/res/drawable-hdpi/btn_check_on_disable_focused.png
index 58ba72d..2037b58 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_disable_focused.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_disable_focused_holo_light.png b/core/res/res/drawable-hdpi/btn_check_on_disable_focused_holo_light.png
index 1f740ad..cdd39c9 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_disable_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_disable_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_disable_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_on_disable_holo_dark.png
index 1f7aeee..f9a5447 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_disable_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_disable_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_disable_holo_light.png b/core/res/res/drawable-hdpi/btn_check_on_disable_holo_light.png
index 1f740ad..cdd39c9 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_disable_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_disable_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_disabled_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_on_disabled_focused_holo_dark.png
index 426f3bb..a175c0f 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_disabled_focused_holo_light.png b/core/res/res/drawable-hdpi/btn_check_on_disabled_focused_holo_light.png
index 67a6c6b..8813f1e 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_disabled_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_on_disabled_holo_dark.png
index cccd61e..72185a6 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_disabled_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_disabled_holo_light.png b/core/res/res/drawable-hdpi/btn_check_on_disabled_holo_light.png
index cd02122..9e34ac8 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_disabled_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_on_focused_holo_dark.png
index 1da69b8..a12a9a4 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_focused_holo_light.png b/core/res/res/drawable-hdpi/btn_check_on_focused_holo_light.png
index 12d7081..68aae57 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_holo.png b/core/res/res/drawable-hdpi/btn_check_on_holo.png
index 7c1bab0..9bffc76 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_holo.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_on_holo_dark.png
index ab2794a..43b7672 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_holo_light.png b/core/res/res/drawable-hdpi/btn_check_on_holo_light.png
index 7cca308..aab514ad 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_pressed.png b/core/res/res/drawable-hdpi/btn_check_on_pressed.png
index 42b8edc..e470e03 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_pressed.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_dark.png
index 7de0448..612f5da 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_light.png b/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_light.png
index 5b916c9..e5ea757 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_selected.png b/core/res/res/drawable-hdpi/btn_check_on_selected.png
index 7c94adf..b0ebc67 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_selected.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_selected.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_circle_disable.png b/core/res/res/drawable-hdpi/btn_circle_disable.png
index 39652a8..82b0c75 100644
--- a/core/res/res/drawable-hdpi/btn_circle_disable.png
+++ b/core/res/res/drawable-hdpi/btn_circle_disable.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_circle_disable_focused.png b/core/res/res/drawable-hdpi/btn_circle_disable_focused.png
index 1aa7ffe..334cb29 100644
--- a/core/res/res/drawable-hdpi/btn_circle_disable_focused.png
+++ b/core/res/res/drawable-hdpi/btn_circle_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_circle_normal.png b/core/res/res/drawable-hdpi/btn_circle_normal.png
index 6011219..2b49d93 100644
--- a/core/res/res/drawable-hdpi/btn_circle_normal.png
+++ b/core/res/res/drawable-hdpi/btn_circle_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_circle_pressed.png b/core/res/res/drawable-hdpi/btn_circle_pressed.png
index 4942e50..d8d1443 100644
--- a/core/res/res/drawable-hdpi/btn_circle_pressed.png
+++ b/core/res/res/drawable-hdpi/btn_circle_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_circle_selected.png b/core/res/res/drawable-hdpi/btn_circle_selected.png
index fe49a40..7df3a22 100644
--- a/core/res/res/drawable-hdpi/btn_circle_selected.png
+++ b/core/res/res/drawable-hdpi/btn_circle_selected.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_close_normal.png b/core/res/res/drawable-hdpi/btn_close_normal.png
index 47f11e5..a9909fb 100644
--- a/core/res/res/drawable-hdpi/btn_close_normal.png
+++ b/core/res/res/drawable-hdpi/btn_close_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_close_pressed.png b/core/res/res/drawable-hdpi/btn_close_pressed.png
index 5b96b4e..39f5125 100644
--- a/core/res/res/drawable-hdpi/btn_close_pressed.png
+++ b/core/res/res/drawable-hdpi/btn_close_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_close_selected.png b/core/res/res/drawable-hdpi/btn_close_selected.png
index e27d684..bbbf20e 100644
--- a/core/res/res/drawable-hdpi/btn_close_selected.png
+++ b/core/res/res/drawable-hdpi/btn_close_selected.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_dark.9.png
index 28a1cba..742e485 100644
--- a/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_light.9.png
index 28a1cba..742e485 100644
--- a/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_holo.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_holo.9.png
index 0437c31..66bf431 100644
--- a/core/res/res/drawable-hdpi/btn_default_disabled_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_holo_dark.9.png
index 72b0d42..13161616 100644
--- a/core/res/res/drawable-hdpi/btn_default_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_holo_light.9.png
index 72b0d42..13161616 100644
--- a/core/res/res/drawable-hdpi/btn_default_disabled_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_focused_holo.9.png b/core/res/res/drawable-hdpi/btn_default_focused_holo.9.png
index 882ed61..1324706 100644
--- a/core/res/res/drawable-hdpi/btn_default_focused_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_focused_holo_dark.9.png
index eff3cc4..85acbbe 100644
--- a/core/res/res/drawable-hdpi/btn_default_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_focused_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_focused_holo_light.9.png
index eff3cc4..85acbbe 100644
--- a/core/res/res/drawable-hdpi/btn_default_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_normal.9.png b/core/res/res/drawable-hdpi/btn_default_normal.9.png
index 803651b..a32ada0 100644
--- a/core/res/res/drawable-hdpi/btn_default_normal.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_normal_disable.9.png b/core/res/res/drawable-hdpi/btn_default_normal_disable.9.png
index f4f01c7..0af19e4 100644
--- a/core/res/res/drawable-hdpi/btn_default_normal_disable.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_normal_disable.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_normal_disable_focused.9.png b/core/res/res/drawable-hdpi/btn_default_normal_disable_focused.9.png
index 5376db2..9c956c4 100644
--- a/core/res/res/drawable-hdpi/btn_default_normal_disable_focused.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_normal_disable_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_normal_holo.9.png b/core/res/res/drawable-hdpi/btn_default_normal_holo.9.png
index dbcede7..bff8ec2 100644
--- a/core/res/res/drawable-hdpi/btn_default_normal_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_normal_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_normal_holo_dark.9.png
index 986f797..ae77fe0 100644
--- a/core/res/res/drawable-hdpi/btn_default_normal_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_normal_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_normal_holo_light.9.png
index 42fc83c..503c17f 100644
--- a/core/res/res/drawable-hdpi/btn_default_normal_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_pressed.9.png b/core/res/res/drawable-hdpi/btn_default_pressed.9.png
index 4312c27..1941eef 100644
--- a/core/res/res/drawable-hdpi/btn_default_pressed.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_pressed_holo.9.png b/core/res/res/drawable-hdpi/btn_default_pressed_holo.9.png
index fd2b63a..4c49335 100644
--- a/core/res/res/drawable-hdpi/btn_default_pressed_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_pressed_holo_dark.9.png
index b7c125b..5470349 100644
--- a/core/res/res/drawable-hdpi/btn_default_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_pressed_holo_light.9.png
index bf09b6f..3b53391 100644
--- a/core/res/res/drawable-hdpi/btn_default_pressed_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_selected.9.png b/core/res/res/drawable-hdpi/btn_default_selected.9.png
index 06b7790..9389d5f 100644
--- a/core/res/res/drawable-hdpi/btn_default_selected.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_small_normal.9.png b/core/res/res/drawable-hdpi/btn_default_small_normal.9.png
index 6d3ea9a..b50a8a5 100644
--- a/core/res/res/drawable-hdpi/btn_default_small_normal.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_small_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_small_normal_disable.9.png b/core/res/res/drawable-hdpi/btn_default_small_normal_disable.9.png
index 2646ba0..cea73af 100644
--- a/core/res/res/drawable-hdpi/btn_default_small_normal_disable.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_small_normal_disable.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_small_normal_disable_focused.9.png b/core/res/res/drawable-hdpi/btn_default_small_normal_disable_focused.9.png
index 013210c..f45a141 100644
--- a/core/res/res/drawable-hdpi/btn_default_small_normal_disable_focused.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_small_normal_disable_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_small_pressed.9.png b/core/res/res/drawable-hdpi/btn_default_small_pressed.9.png
index 24cefd4..e129ba6 100644
--- a/core/res/res/drawable-hdpi/btn_default_small_pressed.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_small_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_small_selected.9.png b/core/res/res/drawable-hdpi/btn_default_small_selected.9.png
index bedbceb..c55f598 100644
--- a/core/res/res/drawable-hdpi/btn_default_small_selected.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_small_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_transparent_normal.9.png b/core/res/res/drawable-hdpi/btn_default_transparent_normal.9.png
index 617dba3..b9bfdb8 100644
--- a/core/res/res/drawable-hdpi/btn_default_transparent_normal.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_transparent_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_dialog_disable.png b/core/res/res/drawable-hdpi/btn_dialog_disable.png
index 4ff634b..2c5137a 100644
--- a/core/res/res/drawable-hdpi/btn_dialog_disable.png
+++ b/core/res/res/drawable-hdpi/btn_dialog_disable.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_dialog_normal.png b/core/res/res/drawable-hdpi/btn_dialog_normal.png
index e0cc339..a9909fb 100644
--- a/core/res/res/drawable-hdpi/btn_dialog_normal.png
+++ b/core/res/res/drawable-hdpi/btn_dialog_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_dialog_pressed.png b/core/res/res/drawable-hdpi/btn_dialog_pressed.png
index ed8e008..f3fc43b 100644
--- a/core/res/res/drawable-hdpi/btn_dialog_pressed.png
+++ b/core/res/res/drawable-hdpi/btn_dialog_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_dialog_selected.png b/core/res/res/drawable-hdpi/btn_dialog_selected.png
index 9b1a100..51624cc 100644
--- a/core/res/res/drawable-hdpi/btn_dialog_selected.png
+++ b/core/res/res/drawable-hdpi/btn_dialog_selected.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_dropdown_disabled.9.png b/core/res/res/drawable-hdpi/btn_dropdown_disabled.9.png
index 0d25b6e..5ba09de 100644
--- a/core/res/res/drawable-hdpi/btn_dropdown_disabled.9.png
+++ b/core/res/res/drawable-hdpi/btn_dropdown_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_dropdown_disabled_focused.9.png b/core/res/res/drawable-hdpi/btn_dropdown_disabled_focused.9.png
index e21fd75..86693de 100644
--- a/core/res/res/drawable-hdpi/btn_dropdown_disabled_focused.9.png
+++ b/core/res/res/drawable-hdpi/btn_dropdown_disabled_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_dropdown_normal.9.png b/core/res/res/drawable-hdpi/btn_dropdown_normal.9.png
index f10402f..f501dc6 100644
--- a/core/res/res/drawable-hdpi/btn_dropdown_normal.9.png
+++ b/core/res/res/drawable-hdpi/btn_dropdown_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_dropdown_pressed.9.png b/core/res/res/drawable-hdpi/btn_dropdown_pressed.9.png
index 366c6e0..afb2e4d 100644
--- a/core/res/res/drawable-hdpi/btn_dropdown_pressed.9.png
+++ b/core/res/res/drawable-hdpi/btn_dropdown_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_dropdown_selected.9.png b/core/res/res/drawable-hdpi/btn_dropdown_selected.9.png
index f063c8d..db6be46 100644
--- a/core/res/res/drawable-hdpi/btn_dropdown_selected.9.png
+++ b/core/res/res/drawable-hdpi/btn_dropdown_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_erase_default.9.png b/core/res/res/drawable-hdpi/btn_erase_default.9.png
index 30984f4..e3f8b53 100644
--- a/core/res/res/drawable-hdpi/btn_erase_default.9.png
+++ b/core/res/res/drawable-hdpi/btn_erase_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_erase_pressed.9.png b/core/res/res/drawable-hdpi/btn_erase_pressed.9.png
index a8225e8..c0b02a7 100644
--- a/core/res/res/drawable-hdpi/btn_erase_pressed.9.png
+++ b/core/res/res/drawable-hdpi/btn_erase_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_erase_selected.9.png b/core/res/res/drawable-hdpi/btn_erase_selected.9.png
index f020f77..b0f9cbe 100644
--- a/core/res/res/drawable-hdpi/btn_erase_selected.9.png
+++ b/core/res/res/drawable-hdpi/btn_erase_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_global_search_normal.9.png b/core/res/res/drawable-hdpi/btn_global_search_normal.9.png
index 5bec4f8..b45f555 100644
--- a/core/res/res/drawable-hdpi/btn_global_search_normal.9.png
+++ b/core/res/res/drawable-hdpi/btn_global_search_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_group_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_group_disabled_holo_dark.9.png
index 00e8f06..b5547da 100644
--- a/core/res/res/drawable-hdpi/btn_group_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_group_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_group_disabled_holo_light.9.png b/core/res/res/drawable-hdpi/btn_group_disabled_holo_light.9.png
index 997ccb2..2e543cb 100644
--- a/core/res/res/drawable-hdpi/btn_group_disabled_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_group_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_group_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_group_focused_holo_dark.9.png
index 824b45a..3b22e50 100644
--- a/core/res/res/drawable-hdpi/btn_group_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_group_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_group_focused_holo_light.9.png b/core/res/res/drawable-hdpi/btn_group_focused_holo_light.9.png
index 824b45a..3b22e50 100644
--- a/core/res/res/drawable-hdpi/btn_group_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_group_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_group_normal_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_group_normal_holo_dark.9.png
index b2120f4..db38b6b 100644
--- a/core/res/res/drawable-hdpi/btn_group_normal_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_group_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_group_normal_holo_light.9.png b/core/res/res/drawable-hdpi/btn_group_normal_holo_light.9.png
index 782d36b..80a1816 100644
--- a/core/res/res/drawable-hdpi/btn_group_normal_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_group_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_group_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_group_pressed_holo_dark.9.png
index 34ec825..4be929e 100644
--- a/core/res/res/drawable-hdpi/btn_group_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_group_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_group_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/btn_group_pressed_holo_light.9.png
index f7680ab..0b32ede 100644
--- a/core/res/res/drawable-hdpi/btn_group_pressed_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_group_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_keyboard_key_dark_normal_holo.9.png b/core/res/res/drawable-hdpi/btn_keyboard_key_dark_normal_holo.9.png
index 5e6a9d6..97db933 100644
--- a/core/res/res/drawable-hdpi/btn_keyboard_key_dark_normal_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_keyboard_key_dark_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_keyboard_key_dark_normal_off_holo.9.png b/core/res/res/drawable-hdpi/btn_keyboard_key_dark_normal_off_holo.9.png
index eb9d740..0416681 100644
--- a/core/res/res/drawable-hdpi/btn_keyboard_key_dark_normal_off_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_keyboard_key_dark_normal_off_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_keyboard_key_dark_normal_on_holo.9.png b/core/res/res/drawable-hdpi/btn_keyboard_key_dark_normal_on_holo.9.png
index 869a330..d244dbb 100644
--- a/core/res/res/drawable-hdpi/btn_keyboard_key_dark_normal_on_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_keyboard_key_dark_normal_on_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_keyboard_key_dark_pressed_holo.9.png b/core/res/res/drawable-hdpi/btn_keyboard_key_dark_pressed_holo.9.png
index 7ec33dd..f4d46be 100644
--- a/core/res/res/drawable-hdpi/btn_keyboard_key_dark_pressed_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_keyboard_key_dark_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off_holo.9.png b/core/res/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off_holo.9.png
index 72d63da..6ad2205 100644
--- a/core/res/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on_holo.9.png b/core/res/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on_holo.9.png
index fcc5cac..ea0f9fa 100644
--- a/core/res/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_keyboard_key_fulltrans_normal.9.png b/core/res/res/drawable-hdpi/btn_keyboard_key_fulltrans_normal.9.png
index b6c234c..d4f6042 100644
--- a/core/res/res/drawable-hdpi/btn_keyboard_key_fulltrans_normal.9.png
+++ b/core/res/res/drawable-hdpi/btn_keyboard_key_fulltrans_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_keyboard_key_fulltrans_normal_off.9.png b/core/res/res/drawable-hdpi/btn_keyboard_key_fulltrans_normal_off.9.png
index 9f3c087..2757df7 100644
--- a/core/res/res/drawable-hdpi/btn_keyboard_key_fulltrans_normal_off.9.png
+++ b/core/res/res/drawable-hdpi/btn_keyboard_key_fulltrans_normal_off.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_keyboard_key_fulltrans_normal_on.9.png b/core/res/res/drawable-hdpi/btn_keyboard_key_fulltrans_normal_on.9.png
index 4041342..034261f 100644
--- a/core/res/res/drawable-hdpi/btn_keyboard_key_fulltrans_normal_on.9.png
+++ b/core/res/res/drawable-hdpi/btn_keyboard_key_fulltrans_normal_on.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_keyboard_key_fulltrans_pressed.9.png b/core/res/res/drawable-hdpi/btn_keyboard_key_fulltrans_pressed.9.png
index 73a8cd1..950d11b 100644
--- a/core/res/res/drawable-hdpi/btn_keyboard_key_fulltrans_pressed.9.png
+++ b/core/res/res/drawable-hdpi/btn_keyboard_key_fulltrans_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_keyboard_key_fulltrans_pressed_off.9.png b/core/res/res/drawable-hdpi/btn_keyboard_key_fulltrans_pressed_off.9.png
index 8473e8e..0621a37 100644
--- a/core/res/res/drawable-hdpi/btn_keyboard_key_fulltrans_pressed_off.9.png
+++ b/core/res/res/drawable-hdpi/btn_keyboard_key_fulltrans_pressed_off.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_keyboard_key_fulltrans_pressed_on.9.png b/core/res/res/drawable-hdpi/btn_keyboard_key_fulltrans_pressed_on.9.png
index f4f59c0..d86302b 100644
--- a/core/res/res/drawable-hdpi/btn_keyboard_key_fulltrans_pressed_on.9.png
+++ b/core/res/res/drawable-hdpi/btn_keyboard_key_fulltrans_pressed_on.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_keyboard_key_light_normal_holo.9.png b/core/res/res/drawable-hdpi/btn_keyboard_key_light_normal_holo.9.png
index baff858..dd4815b 100644
--- a/core/res/res/drawable-hdpi/btn_keyboard_key_light_normal_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_keyboard_key_light_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_keyboard_key_light_pressed_holo.9.png b/core/res/res/drawable-hdpi/btn_keyboard_key_light_pressed_holo.9.png
index 5612c51..8617758 100644
--- a/core/res/res/drawable-hdpi/btn_keyboard_key_light_pressed_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_keyboard_key_light_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_keyboard_key_normal.9.png b/core/res/res/drawable-hdpi/btn_keyboard_key_normal.9.png
index 42c7c146..7de5b27 100644
--- a/core/res/res/drawable-hdpi/btn_keyboard_key_normal.9.png
+++ b/core/res/res/drawable-hdpi/btn_keyboard_key_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_keyboard_key_normal_off.9.png b/core/res/res/drawable-hdpi/btn_keyboard_key_normal_off.9.png
index 01e2506..743cdbe 100644
--- a/core/res/res/drawable-hdpi/btn_keyboard_key_normal_off.9.png
+++ b/core/res/res/drawable-hdpi/btn_keyboard_key_normal_off.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_keyboard_key_normal_on.9.png b/core/res/res/drawable-hdpi/btn_keyboard_key_normal_on.9.png
index 83c6eb3..2033a2c 100644
--- a/core/res/res/drawable-hdpi/btn_keyboard_key_normal_on.9.png
+++ b/core/res/res/drawable-hdpi/btn_keyboard_key_normal_on.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_keyboard_key_pressed.9.png b/core/res/res/drawable-hdpi/btn_keyboard_key_pressed.9.png
index e047eaf..692bb853 100644
--- a/core/res/res/drawable-hdpi/btn_keyboard_key_pressed.9.png
+++ b/core/res/res/drawable-hdpi/btn_keyboard_key_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_keyboard_key_pressed_off.9.png b/core/res/res/drawable-hdpi/btn_keyboard_key_pressed_off.9.png
index 218a2d2..461be22 100644
--- a/core/res/res/drawable-hdpi/btn_keyboard_key_pressed_off.9.png
+++ b/core/res/res/drawable-hdpi/btn_keyboard_key_pressed_off.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_keyboard_key_pressed_on.9.png b/core/res/res/drawable-hdpi/btn_keyboard_key_pressed_on.9.png
index afe4951..5d679c5 100644
--- a/core/res/res/drawable-hdpi/btn_keyboard_key_pressed_on.9.png
+++ b/core/res/res/drawable-hdpi/btn_keyboard_key_pressed_on.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_keyboard_key_trans_normal.9.png b/core/res/res/drawable-hdpi/btn_keyboard_key_trans_normal.9.png
index 9c7e483..8299705 100644
--- a/core/res/res/drawable-hdpi/btn_keyboard_key_trans_normal.9.png
+++ b/core/res/res/drawable-hdpi/btn_keyboard_key_trans_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_keyboard_key_trans_normal_off.9.png b/core/res/res/drawable-hdpi/btn_keyboard_key_trans_normal_off.9.png
index 1508653..7d39f5e 100644
--- a/core/res/res/drawable-hdpi/btn_keyboard_key_trans_normal_off.9.png
+++ b/core/res/res/drawable-hdpi/btn_keyboard_key_trans_normal_off.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_keyboard_key_trans_normal_on.9.png b/core/res/res/drawable-hdpi/btn_keyboard_key_trans_normal_on.9.png
index 66c231a..f6472cc 100644
--- a/core/res/res/drawable-hdpi/btn_keyboard_key_trans_normal_on.9.png
+++ b/core/res/res/drawable-hdpi/btn_keyboard_key_trans_normal_on.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_keyboard_key_trans_pressed.9.png b/core/res/res/drawable-hdpi/btn_keyboard_key_trans_pressed.9.png
index e01a49d..37d3397 100644
--- a/core/res/res/drawable-hdpi/btn_keyboard_key_trans_pressed.9.png
+++ b/core/res/res/drawable-hdpi/btn_keyboard_key_trans_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_keyboard_key_trans_pressed_off.9.png b/core/res/res/drawable-hdpi/btn_keyboard_key_trans_pressed_off.9.png
index cdad182..53bcb9fa 100644
--- a/core/res/res/drawable-hdpi/btn_keyboard_key_trans_pressed_off.9.png
+++ b/core/res/res/drawable-hdpi/btn_keyboard_key_trans_pressed_off.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_keyboard_key_trans_pressed_on.9.png b/core/res/res/drawable-hdpi/btn_keyboard_key_trans_pressed_on.9.png
index e95f4cf..10268d7 100644
--- a/core/res/res/drawable-hdpi/btn_keyboard_key_trans_pressed_on.9.png
+++ b/core/res/res/drawable-hdpi/btn_keyboard_key_trans_pressed_on.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_keyboard_key_trans_selected.9.png b/core/res/res/drawable-hdpi/btn_keyboard_key_trans_selected.9.png
index 544655e..49076739 100644
--- a/core/res/res/drawable-hdpi/btn_keyboard_key_trans_selected.9.png
+++ b/core/res/res/drawable-hdpi/btn_keyboard_key_trans_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_media_player.9.png b/core/res/res/drawable-hdpi/btn_media_player.9.png
index bf16315..580f568 100644
--- a/core/res/res/drawable-hdpi/btn_media_player.9.png
+++ b/core/res/res/drawable-hdpi/btn_media_player.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_media_player_disabled.9.png b/core/res/res/drawable-hdpi/btn_media_player_disabled.9.png
index d7b8ed5..7aedf13 100644
--- a/core/res/res/drawable-hdpi/btn_media_player_disabled.9.png
+++ b/core/res/res/drawable-hdpi/btn_media_player_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_media_player_disabled_selected.9.png b/core/res/res/drawable-hdpi/btn_media_player_disabled_selected.9.png
index 1a35c31..24118a6 100644
--- a/core/res/res/drawable-hdpi/btn_media_player_disabled_selected.9.png
+++ b/core/res/res/drawable-hdpi/btn_media_player_disabled_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_media_player_pressed.9.png b/core/res/res/drawable-hdpi/btn_media_player_pressed.9.png
index 17dd3fc..54fcf64 100644
--- a/core/res/res/drawable-hdpi/btn_media_player_pressed.9.png
+++ b/core/res/res/drawable-hdpi/btn_media_player_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_media_player_selected.9.png b/core/res/res/drawable-hdpi/btn_media_player_selected.9.png
index a146d8f..9b583a10 100644
--- a/core/res/res/drawable-hdpi/btn_media_player_selected.9.png
+++ b/core/res/res/drawable-hdpi/btn_media_player_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_minus_default.png b/core/res/res/drawable-hdpi/btn_minus_default.png
index f2831af..a84a82b 100644
--- a/core/res/res/drawable-hdpi/btn_minus_default.png
+++ b/core/res/res/drawable-hdpi/btn_minus_default.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_minus_disable.png b/core/res/res/drawable-hdpi/btn_minus_disable.png
index 24ce695..6da53c0 100644
--- a/core/res/res/drawable-hdpi/btn_minus_disable.png
+++ b/core/res/res/drawable-hdpi/btn_minus_disable.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_minus_disable_focused.png b/core/res/res/drawable-hdpi/btn_minus_disable_focused.png
index e92c2b1..90707e4 100644
--- a/core/res/res/drawable-hdpi/btn_minus_disable_focused.png
+++ b/core/res/res/drawable-hdpi/btn_minus_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_minus_pressed.png b/core/res/res/drawable-hdpi/btn_minus_pressed.png
index ba2ed26..3cd496f 100644
--- a/core/res/res/drawable-hdpi/btn_minus_pressed.png
+++ b/core/res/res/drawable-hdpi/btn_minus_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_minus_selected.png b/core/res/res/drawable-hdpi/btn_minus_selected.png
index 6b938b3..61a0cc5 100644
--- a/core/res/res/drawable-hdpi/btn_minus_selected.png
+++ b/core/res/res/drawable-hdpi/btn_minus_selected.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_plus_default.png b/core/res/res/drawable-hdpi/btn_plus_default.png
index 441d1fb..758c482 100644
--- a/core/res/res/drawable-hdpi/btn_plus_default.png
+++ b/core/res/res/drawable-hdpi/btn_plus_default.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_plus_disable.png b/core/res/res/drawable-hdpi/btn_plus_disable.png
index 4e965c1..1b04465 100644
--- a/core/res/res/drawable-hdpi/btn_plus_disable.png
+++ b/core/res/res/drawable-hdpi/btn_plus_disable.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_plus_disable_focused.png b/core/res/res/drawable-hdpi/btn_plus_disable_focused.png
index 0c938eb..efac205 100644
--- a/core/res/res/drawable-hdpi/btn_plus_disable_focused.png
+++ b/core/res/res/drawable-hdpi/btn_plus_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_plus_pressed.png b/core/res/res/drawable-hdpi/btn_plus_pressed.png
index 8dd5a68..500294b 100644
--- a/core/res/res/drawable-hdpi/btn_plus_pressed.png
+++ b/core/res/res/drawable-hdpi/btn_plus_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_plus_selected.png b/core/res/res/drawable-hdpi/btn_plus_selected.png
index 8fe30ed..f6a30e8 100644
--- a/core/res/res/drawable-hdpi/btn_plus_selected.png
+++ b/core/res/res/drawable-hdpi/btn_plus_selected.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_label_background.9.png b/core/res/res/drawable-hdpi/btn_radio_label_background.9.png
index 45c5c6a..6c4ab91 100644
--- a/core/res/res/drawable-hdpi/btn_radio_label_background.9.png
+++ b/core/res/res/drawable-hdpi/btn_radio_label_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_off.png b/core/res/res/drawable-hdpi/btn_radio_off.png
index 48ee2ba..6cf7d52 100644
--- a/core/res/res/drawable-hdpi/btn_radio_off.png
+++ b/core/res/res/drawable-hdpi/btn_radio_off.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_off_disabled_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_radio_off_disabled_focused_holo_dark.png
index 652a528..6606444 100644
--- a/core/res/res/drawable-hdpi/btn_radio_off_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_radio_off_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_off_disabled_focused_holo_light.png b/core/res/res/drawable-hdpi/btn_radio_off_disabled_focused_holo_light.png
index cd73cd20..ba64377 100644
--- a/core/res/res/drawable-hdpi/btn_radio_off_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_radio_off_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_off_disabled_holo_dark.png b/core/res/res/drawable-hdpi/btn_radio_off_disabled_holo_dark.png
index eb58648..2c1e945 100644
--- a/core/res/res/drawable-hdpi/btn_radio_off_disabled_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_radio_off_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_off_disabled_holo_light.png b/core/res/res/drawable-hdpi/btn_radio_off_disabled_holo_light.png
index 25e8e1b..d096afa 100644
--- a/core/res/res/drawable-hdpi/btn_radio_off_disabled_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_radio_off_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_off_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_radio_off_focused_holo_dark.png
index db79042..2cf6914 100644
--- a/core/res/res/drawable-hdpi/btn_radio_off_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_radio_off_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_off_focused_holo_light.png b/core/res/res/drawable-hdpi/btn_radio_off_focused_holo_light.png
index bba1e26..5342c14 100644
--- a/core/res/res/drawable-hdpi/btn_radio_off_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_radio_off_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_off_holo.png b/core/res/res/drawable-hdpi/btn_radio_off_holo.png
index e2761d2..559b76a 100644
--- a/core/res/res/drawable-hdpi/btn_radio_off_holo.png
+++ b/core/res/res/drawable-hdpi/btn_radio_off_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_off_holo_dark.png b/core/res/res/drawable-hdpi/btn_radio_off_holo_dark.png
index ff5510e..f287ba5 100644
--- a/core/res/res/drawable-hdpi/btn_radio_off_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_radio_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_off_holo_light.png b/core/res/res/drawable-hdpi/btn_radio_off_holo_light.png
index 4d60008..702fb04 100644
--- a/core/res/res/drawable-hdpi/btn_radio_off_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_radio_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_off_pressed.png b/core/res/res/drawable-hdpi/btn_radio_off_pressed.png
index 5a4ad89..61ba28c 100644
--- a/core/res/res/drawable-hdpi/btn_radio_off_pressed.png
+++ b/core/res/res/drawable-hdpi/btn_radio_off_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_off_pressed_holo_dark.png b/core/res/res/drawable-hdpi/btn_radio_off_pressed_holo_dark.png
index 9fd5b764..4d64ecc 100644
--- a/core/res/res/drawable-hdpi/btn_radio_off_pressed_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_radio_off_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_off_pressed_holo_light.png b/core/res/res/drawable-hdpi/btn_radio_off_pressed_holo_light.png
index caff83d..2bad796 100644
--- a/core/res/res/drawable-hdpi/btn_radio_off_pressed_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_radio_off_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_off_selected.png b/core/res/res/drawable-hdpi/btn_radio_off_selected.png
index 7d5c676..12185cd 100644
--- a/core/res/res/drawable-hdpi/btn_radio_off_selected.png
+++ b/core/res/res/drawable-hdpi/btn_radio_off_selected.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_on.png b/core/res/res/drawable-hdpi/btn_radio_on.png
index 2472c20..accbee7 100644
--- a/core/res/res/drawable-hdpi/btn_radio_on.png
+++ b/core/res/res/drawable-hdpi/btn_radio_on.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_on_disabled_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_radio_on_disabled_focused_holo_dark.png
index d9cee46..96b9b2b 100644
--- a/core/res/res/drawable-hdpi/btn_radio_on_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_radio_on_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_on_disabled_focused_holo_light.png b/core/res/res/drawable-hdpi/btn_radio_on_disabled_focused_holo_light.png
index 3895dba1..1f2f0b2 100644
--- a/core/res/res/drawable-hdpi/btn_radio_on_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_radio_on_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_on_disabled_holo_dark.png b/core/res/res/drawable-hdpi/btn_radio_on_disabled_holo_dark.png
index 6ebb184..f407478 100644
--- a/core/res/res/drawable-hdpi/btn_radio_on_disabled_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_radio_on_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_on_disabled_holo_light.png b/core/res/res/drawable-hdpi/btn_radio_on_disabled_holo_light.png
index 6e61b52..dfa64f0 100644
--- a/core/res/res/drawable-hdpi/btn_radio_on_disabled_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_radio_on_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_on_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_radio_on_focused_holo_dark.png
index 13664b7..24acb5d 100644
--- a/core/res/res/drawable-hdpi/btn_radio_on_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_radio_on_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_on_focused_holo_light.png b/core/res/res/drawable-hdpi/btn_radio_on_focused_holo_light.png
index fddb7dd..e49da132 100644
--- a/core/res/res/drawable-hdpi/btn_radio_on_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_radio_on_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_on_holo.png b/core/res/res/drawable-hdpi/btn_radio_on_holo.png
index fdaffdc..414d710 100644
--- a/core/res/res/drawable-hdpi/btn_radio_on_holo.png
+++ b/core/res/res/drawable-hdpi/btn_radio_on_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_on_holo_dark.png b/core/res/res/drawable-hdpi/btn_radio_on_holo_dark.png
index 0a31436..77d3c5a 100644
--- a/core/res/res/drawable-hdpi/btn_radio_on_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_radio_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_on_holo_light.png b/core/res/res/drawable-hdpi/btn_radio_on_holo_light.png
index b843f77..39f2dc0 100644
--- a/core/res/res/drawable-hdpi/btn_radio_on_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_radio_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_on_pressed.png b/core/res/res/drawable-hdpi/btn_radio_on_pressed.png
index 98d74ce..ff8c176 100644
--- a/core/res/res/drawable-hdpi/btn_radio_on_pressed.png
+++ b/core/res/res/drawable-hdpi/btn_radio_on_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_on_pressed_holo_dark.png b/core/res/res/drawable-hdpi/btn_radio_on_pressed_holo_dark.png
index 4cddfda..2dc756a 100644
--- a/core/res/res/drawable-hdpi/btn_radio_on_pressed_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_radio_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_on_pressed_holo_light.png b/core/res/res/drawable-hdpi/btn_radio_on_pressed_holo_light.png
index e94aabe..cccd8fd 100644
--- a/core/res/res/drawable-hdpi/btn_radio_on_pressed_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_radio_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_on_selected.png b/core/res/res/drawable-hdpi/btn_radio_on_selected.png
index b6ab46c..08c4647 100644
--- a/core/res/res/drawable-hdpi/btn_radio_on_selected.png
+++ b/core/res/res/drawable-hdpi/btn_radio_on_selected.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_rating_star_off_disabled_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_rating_star_off_disabled_focused_holo_dark.png
index 961b0f7..73bdc69 100644
--- a/core/res/res/drawable-hdpi/btn_rating_star_off_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_rating_star_off_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_rating_star_off_disabled_focused_holo_light.png b/core/res/res/drawable-hdpi/btn_rating_star_off_disabled_focused_holo_light.png
index 503de5c..e0dfd95 100644
--- a/core/res/res/drawable-hdpi/btn_rating_star_off_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_rating_star_off_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_rating_star_off_disabled_holo_dark.png b/core/res/res/drawable-hdpi/btn_rating_star_off_disabled_holo_dark.png
index a756e30..3a6cde4 100644
--- a/core/res/res/drawable-hdpi/btn_rating_star_off_disabled_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_rating_star_off_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_rating_star_off_disabled_holo_light.png b/core/res/res/drawable-hdpi/btn_rating_star_off_disabled_holo_light.png
index 0d5bbe8..d70cc22 100644
--- a/core/res/res/drawable-hdpi/btn_rating_star_off_disabled_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_rating_star_off_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_rating_star_off_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_rating_star_off_focused_holo_dark.png
index c58a841..e5efead 100644
--- a/core/res/res/drawable-hdpi/btn_rating_star_off_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_rating_star_off_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_rating_star_off_focused_holo_light.png b/core/res/res/drawable-hdpi/btn_rating_star_off_focused_holo_light.png
index 9e018ef..8db966a 100644
--- a/core/res/res/drawable-hdpi/btn_rating_star_off_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_rating_star_off_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_rating_star_off_mtrl_alpha.png b/core/res/res/drawable-hdpi/btn_rating_star_off_mtrl_alpha.png
index 51a895d..d5e14c9 100644
--- a/core/res/res/drawable-hdpi/btn_rating_star_off_mtrl_alpha.png
+++ b/core/res/res/drawable-hdpi/btn_rating_star_off_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_rating_star_off_normal.png b/core/res/res/drawable-hdpi/btn_rating_star_off_normal.png
index d119807..784733d 100644
--- a/core/res/res/drawable-hdpi/btn_rating_star_off_normal.png
+++ b/core/res/res/drawable-hdpi/btn_rating_star_off_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_rating_star_off_normal_holo_dark.png b/core/res/res/drawable-hdpi/btn_rating_star_off_normal_holo_dark.png
index afaf691..384340a 100644
--- a/core/res/res/drawable-hdpi/btn_rating_star_off_normal_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_rating_star_off_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_rating_star_off_normal_holo_light.png b/core/res/res/drawable-hdpi/btn_rating_star_off_normal_holo_light.png
index 26adc72..e751990 100644
--- a/core/res/res/drawable-hdpi/btn_rating_star_off_normal_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_rating_star_off_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_rating_star_off_pressed.png b/core/res/res/drawable-hdpi/btn_rating_star_off_pressed.png
index 6f76da3..8586081 100644
--- a/core/res/res/drawable-hdpi/btn_rating_star_off_pressed.png
+++ b/core/res/res/drawable-hdpi/btn_rating_star_off_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_rating_star_off_pressed_holo_dark.png b/core/res/res/drawable-hdpi/btn_rating_star_off_pressed_holo_dark.png
index e0cc6c5..a3cca0b 100644
--- a/core/res/res/drawable-hdpi/btn_rating_star_off_pressed_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_rating_star_off_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_rating_star_off_pressed_holo_light.png b/core/res/res/drawable-hdpi/btn_rating_star_off_pressed_holo_light.png
index 607d1cf..aa5c348 100644
--- a/core/res/res/drawable-hdpi/btn_rating_star_off_pressed_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_rating_star_off_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_rating_star_off_selected.png b/core/res/res/drawable-hdpi/btn_rating_star_off_selected.png
index 566090d..e79878a 100644
--- a/core/res/res/drawable-hdpi/btn_rating_star_off_selected.png
+++ b/core/res/res/drawable-hdpi/btn_rating_star_off_selected.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_rating_star_on_disabled_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_rating_star_on_disabled_focused_holo_dark.png
index 4791366..6081034 100644
--- a/core/res/res/drawable-hdpi/btn_rating_star_on_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_rating_star_on_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_rating_star_on_disabled_focused_holo_light.png b/core/res/res/drawable-hdpi/btn_rating_star_on_disabled_focused_holo_light.png
index 8680012..a0d9bd0 100644
--- a/core/res/res/drawable-hdpi/btn_rating_star_on_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_rating_star_on_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_rating_star_on_disabled_holo_dark.png b/core/res/res/drawable-hdpi/btn_rating_star_on_disabled_holo_dark.png
index 7dc2567..af77c6a 100644
--- a/core/res/res/drawable-hdpi/btn_rating_star_on_disabled_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_rating_star_on_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_rating_star_on_disabled_holo_light.png b/core/res/res/drawable-hdpi/btn_rating_star_on_disabled_holo_light.png
index de02ace..4382932 100644
--- a/core/res/res/drawable-hdpi/btn_rating_star_on_disabled_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_rating_star_on_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_rating_star_on_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_rating_star_on_focused_holo_dark.png
index 9b34307..950ef00 100644
--- a/core/res/res/drawable-hdpi/btn_rating_star_on_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_rating_star_on_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_rating_star_on_focused_holo_light.png b/core/res/res/drawable-hdpi/btn_rating_star_on_focused_holo_light.png
index fc9af78..60c63c8 100644
--- a/core/res/res/drawable-hdpi/btn_rating_star_on_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_rating_star_on_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_rating_star_on_mtrl_alpha.png b/core/res/res/drawable-hdpi/btn_rating_star_on_mtrl_alpha.png
index 2f59488..491d9f9 100644
--- a/core/res/res/drawable-hdpi/btn_rating_star_on_mtrl_alpha.png
+++ b/core/res/res/drawable-hdpi/btn_rating_star_on_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_rating_star_on_normal.png b/core/res/res/drawable-hdpi/btn_rating_star_on_normal.png
index c55c1f6..a6daac5 100644
--- a/core/res/res/drawable-hdpi/btn_rating_star_on_normal.png
+++ b/core/res/res/drawable-hdpi/btn_rating_star_on_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_rating_star_on_normal_holo_dark.png b/core/res/res/drawable-hdpi/btn_rating_star_on_normal_holo_dark.png
index c22ac4c..46fb980 100644
--- a/core/res/res/drawable-hdpi/btn_rating_star_on_normal_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_rating_star_on_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_rating_star_on_normal_holo_light.png b/core/res/res/drawable-hdpi/btn_rating_star_on_normal_holo_light.png
index b2b0e29..60744c3 100644
--- a/core/res/res/drawable-hdpi/btn_rating_star_on_normal_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_rating_star_on_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_rating_star_on_pressed.png b/core/res/res/drawable-hdpi/btn_rating_star_on_pressed.png
index 89b8161..b1f5897 100644
--- a/core/res/res/drawable-hdpi/btn_rating_star_on_pressed.png
+++ b/core/res/res/drawable-hdpi/btn_rating_star_on_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_rating_star_on_pressed_holo_dark.png b/core/res/res/drawable-hdpi/btn_rating_star_on_pressed_holo_dark.png
index f45882c..49e4579 100644
--- a/core/res/res/drawable-hdpi/btn_rating_star_on_pressed_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_rating_star_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_rating_star_on_pressed_holo_light.png b/core/res/res/drawable-hdpi/btn_rating_star_on_pressed_holo_light.png
index d06fbeb..0f54b95 100644
--- a/core/res/res/drawable-hdpi/btn_rating_star_on_pressed_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_rating_star_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_rating_star_on_selected.png b/core/res/res/drawable-hdpi/btn_rating_star_on_selected.png
index 1a76a26..aace100 100644
--- a/core/res/res/drawable-hdpi/btn_rating_star_on_selected.png
+++ b/core/res/res/drawable-hdpi/btn_rating_star_on_selected.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_search_dialog_default.9.png b/core/res/res/drawable-hdpi/btn_search_dialog_default.9.png
index 72faccf..048dcfd 100644
--- a/core/res/res/drawable-hdpi/btn_search_dialog_default.9.png
+++ b/core/res/res/drawable-hdpi/btn_search_dialog_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_search_dialog_pressed.9.png b/core/res/res/drawable-hdpi/btn_search_dialog_pressed.9.png
index 369be10..1713822 100644
--- a/core/res/res/drawable-hdpi/btn_search_dialog_pressed.9.png
+++ b/core/res/res/drawable-hdpi/btn_search_dialog_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_search_dialog_selected.9.png b/core/res/res/drawable-hdpi/btn_search_dialog_selected.9.png
index 7e996ec..a7f2230 100644
--- a/core/res/res/drawable-hdpi/btn_search_dialog_selected.9.png
+++ b/core/res/res/drawable-hdpi/btn_search_dialog_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_search_dialog_voice_default.9.png b/core/res/res/drawable-hdpi/btn_search_dialog_voice_default.9.png
index eda6e16..dbe0f97 100644
--- a/core/res/res/drawable-hdpi/btn_search_dialog_voice_default.9.png
+++ b/core/res/res/drawable-hdpi/btn_search_dialog_voice_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_search_dialog_voice_pressed.9.png b/core/res/res/drawable-hdpi/btn_search_dialog_voice_pressed.9.png
index 4158ac4..1659f537 100644
--- a/core/res/res/drawable-hdpi/btn_search_dialog_voice_pressed.9.png
+++ b/core/res/res/drawable-hdpi/btn_search_dialog_voice_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_search_dialog_voice_selected.9.png b/core/res/res/drawable-hdpi/btn_search_dialog_voice_selected.9.png
index 6f68f25..881d42b 100644
--- a/core/res/res/drawable-hdpi/btn_search_dialog_voice_selected.9.png
+++ b/core/res/res/drawable-hdpi/btn_search_dialog_voice_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_square_overlay_disabled.png b/core/res/res/drawable-hdpi/btn_square_overlay_disabled.png
index 71a037e..1d07648 100644
--- a/core/res/res/drawable-hdpi/btn_square_overlay_disabled.png
+++ b/core/res/res/drawable-hdpi/btn_square_overlay_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_square_overlay_disabled_focused.png b/core/res/res/drawable-hdpi/btn_square_overlay_disabled_focused.png
index a474605..337e113 100644
--- a/core/res/res/drawable-hdpi/btn_square_overlay_disabled_focused.png
+++ b/core/res/res/drawable-hdpi/btn_square_overlay_disabled_focused.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_square_overlay_normal.png b/core/res/res/drawable-hdpi/btn_square_overlay_normal.png
index bf5da22..0226efd 100644
--- a/core/res/res/drawable-hdpi/btn_square_overlay_normal.png
+++ b/core/res/res/drawable-hdpi/btn_square_overlay_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_square_overlay_pressed.png b/core/res/res/drawable-hdpi/btn_square_overlay_pressed.png
index 52a302d..9d8ae71 100644
--- a/core/res/res/drawable-hdpi/btn_square_overlay_pressed.png
+++ b/core/res/res/drawable-hdpi/btn_square_overlay_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_square_overlay_selected.png b/core/res/res/drawable-hdpi/btn_square_overlay_selected.png
index e065682..6e1f2ce 100644
--- a/core/res/res/drawable-hdpi/btn_square_overlay_selected.png
+++ b/core/res/res/drawable-hdpi/btn_square_overlay_selected.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_big_off.png b/core/res/res/drawable-hdpi/btn_star_big_off.png
index 4be0f5d..77d571ece 100644
--- a/core/res/res/drawable-hdpi/btn_star_big_off.png
+++ b/core/res/res/drawable-hdpi/btn_star_big_off.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_big_off_disable.png b/core/res/res/drawable-hdpi/btn_star_big_off_disable.png
index faba665..abbc7d2 100644
--- a/core/res/res/drawable-hdpi/btn_star_big_off_disable.png
+++ b/core/res/res/drawable-hdpi/btn_star_big_off_disable.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_big_off_disable_focused.png b/core/res/res/drawable-hdpi/btn_star_big_off_disable_focused.png
index fc8aca4..9d89dd6 100644
--- a/core/res/res/drawable-hdpi/btn_star_big_off_disable_focused.png
+++ b/core/res/res/drawable-hdpi/btn_star_big_off_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_big_off_pressed.png b/core/res/res/drawable-hdpi/btn_star_big_off_pressed.png
index b8c8e70..e50b9b9 100644
--- a/core/res/res/drawable-hdpi/btn_star_big_off_pressed.png
+++ b/core/res/res/drawable-hdpi/btn_star_big_off_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_big_off_selected.png b/core/res/res/drawable-hdpi/btn_star_big_off_selected.png
index 86250bb..2747e73 100644
--- a/core/res/res/drawable-hdpi/btn_star_big_off_selected.png
+++ b/core/res/res/drawable-hdpi/btn_star_big_off_selected.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_big_on.png b/core/res/res/drawable-hdpi/btn_star_big_on.png
index 4213050..2be7194 100644
--- a/core/res/res/drawable-hdpi/btn_star_big_on.png
+++ b/core/res/res/drawable-hdpi/btn_star_big_on.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_big_on_disable.png b/core/res/res/drawable-hdpi/btn_star_big_on_disable.png
index 5629849..4260edf 100644
--- a/core/res/res/drawable-hdpi/btn_star_big_on_disable.png
+++ b/core/res/res/drawable-hdpi/btn_star_big_on_disable.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_big_on_disable_focused.png b/core/res/res/drawable-hdpi/btn_star_big_on_disable_focused.png
index cb9f79c..6ffc61d 100644
--- a/core/res/res/drawable-hdpi/btn_star_big_on_disable_focused.png
+++ b/core/res/res/drawable-hdpi/btn_star_big_on_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_big_on_pressed.png b/core/res/res/drawable-hdpi/btn_star_big_on_pressed.png
index 648cd1b..9d99ad5 100644
--- a/core/res/res/drawable-hdpi/btn_star_big_on_pressed.png
+++ b/core/res/res/drawable-hdpi/btn_star_big_on_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_big_on_selected.png b/core/res/res/drawable-hdpi/btn_star_big_on_selected.png
index cb15673..84abb30 100644
--- a/core/res/res/drawable-hdpi/btn_star_big_on_selected.png
+++ b/core/res/res/drawable-hdpi/btn_star_big_on_selected.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_label_background.9.png b/core/res/res/drawable-hdpi/btn_star_label_background.9.png
index 6008067..11d2dc0 100644
--- a/core/res/res/drawable-hdpi/btn_star_label_background.9.png
+++ b/core/res/res/drawable-hdpi/btn_star_label_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_mtrl_alpha.png b/core/res/res/drawable-hdpi/btn_star_mtrl_alpha.png
index e11896f6..133009b 100644
--- a/core/res/res/drawable-hdpi/btn_star_mtrl_alpha.png
+++ b/core/res/res/drawable-hdpi/btn_star_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_off_disabled_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_star_off_disabled_focused_holo_dark.png
index ce3954f..74f8fd2 100644
--- a/core/res/res/drawable-hdpi/btn_star_off_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_star_off_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_off_disabled_focused_holo_light.png b/core/res/res/drawable-hdpi/btn_star_off_disabled_focused_holo_light.png
index 2e7346a..be496a6 100644
--- a/core/res/res/drawable-hdpi/btn_star_off_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_star_off_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_off_disabled_holo_dark.png b/core/res/res/drawable-hdpi/btn_star_off_disabled_holo_dark.png
index 1a642f7..2775ee1 100644
--- a/core/res/res/drawable-hdpi/btn_star_off_disabled_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_star_off_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_off_disabled_holo_light.png b/core/res/res/drawable-hdpi/btn_star_off_disabled_holo_light.png
index cee608b..809f4f8 100644
--- a/core/res/res/drawable-hdpi/btn_star_off_disabled_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_star_off_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_off_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_star_off_focused_holo_dark.png
index 0eb9e38..6cf7180 100644
--- a/core/res/res/drawable-hdpi/btn_star_off_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_star_off_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_off_focused_holo_light.png b/core/res/res/drawable-hdpi/btn_star_off_focused_holo_light.png
index f396c47..0ebcfa0 100644
--- a/core/res/res/drawable-hdpi/btn_star_off_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_star_off_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_off_normal_holo_dark.png b/core/res/res/drawable-hdpi/btn_star_off_normal_holo_dark.png
index cbbbfb3..f9a90ea 100644
--- a/core/res/res/drawable-hdpi/btn_star_off_normal_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_star_off_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_off_normal_holo_light.png b/core/res/res/drawable-hdpi/btn_star_off_normal_holo_light.png
index c4e1d81f..d7125c4 100644
--- a/core/res/res/drawable-hdpi/btn_star_off_normal_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_star_off_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_off_pressed_holo_dark.png b/core/res/res/drawable-hdpi/btn_star_off_pressed_holo_dark.png
index 97730d1..62c6c79 100644
--- a/core/res/res/drawable-hdpi/btn_star_off_pressed_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_star_off_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_off_pressed_holo_light.png b/core/res/res/drawable-hdpi/btn_star_off_pressed_holo_light.png
index 4350f16..fa67b0a 100644
--- a/core/res/res/drawable-hdpi/btn_star_off_pressed_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_star_off_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_on_disabled_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_star_on_disabled_focused_holo_dark.png
index b7035fd..aa284fb 100644
--- a/core/res/res/drawable-hdpi/btn_star_on_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_star_on_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_on_disabled_focused_holo_light.png b/core/res/res/drawable-hdpi/btn_star_on_disabled_focused_holo_light.png
index 852ad55..e77db9f 100644
--- a/core/res/res/drawable-hdpi/btn_star_on_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_star_on_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_on_disabled_holo_dark.png b/core/res/res/drawable-hdpi/btn_star_on_disabled_holo_dark.png
index 3d40107..89a5a39 100644
--- a/core/res/res/drawable-hdpi/btn_star_on_disabled_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_star_on_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_on_disabled_holo_light.png b/core/res/res/drawable-hdpi/btn_star_on_disabled_holo_light.png
index ee79ed6..0855b28 100644
--- a/core/res/res/drawable-hdpi/btn_star_on_disabled_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_star_on_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_on_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_star_on_focused_holo_dark.png
index 6cad71e..7237d9b 100644
--- a/core/res/res/drawable-hdpi/btn_star_on_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_star_on_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_on_focused_holo_light.png b/core/res/res/drawable-hdpi/btn_star_on_focused_holo_light.png
index edcb86d..762c453 100644
--- a/core/res/res/drawable-hdpi/btn_star_on_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_star_on_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_on_normal_holo_dark.png b/core/res/res/drawable-hdpi/btn_star_on_normal_holo_dark.png
index 02013fa..547064e 100644
--- a/core/res/res/drawable-hdpi/btn_star_on_normal_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_star_on_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_on_normal_holo_light.png b/core/res/res/drawable-hdpi/btn_star_on_normal_holo_light.png
index 6689a89..127732b 100644
--- a/core/res/res/drawable-hdpi/btn_star_on_normal_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_star_on_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_on_pressed_holo_dark.png b/core/res/res/drawable-hdpi/btn_star_on_pressed_holo_dark.png
index 36f9ad1..c7ce1ef 100644
--- a/core/res/res/drawable-hdpi/btn_star_on_pressed_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_star_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_on_pressed_holo_light.png b/core/res/res/drawable-hdpi/btn_star_on_pressed_holo_light.png
index 10d74ce..647a196 100644
--- a/core/res/res/drawable-hdpi/btn_star_on_pressed_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_star_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00001.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00001.9.png
index c31194e..6b5242c 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00001.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00002.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00002.9.png
index 52ed6b2..711da1d 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00002.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00003.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00003.9.png
index 7b7cde586..e93dbdf 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00003.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00004.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00004.9.png
index 859642a..941f9a1 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00004.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00005.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00005.9.png
index 5b71dda..9e009dc7 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00005.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00006.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00006.9.png
index 378d82d..03f29c2 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00006.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00007.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00007.9.png
index 43c995a..29674d9 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00007.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00008.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00008.9.png
index c937837..2dbe4f8 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00008.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00009.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00009.9.png
index a60a127..5c87ae2 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00009.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00010.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00010.9.png
index db0bf2d..5c24cff 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00010.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00011.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00011.9.png
index 4a6adbe..d168bc2 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00011.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00012.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00012.9.png
index 98983ef..d0d6b8e 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00012.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00001.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00001.9.png
index 8e7b62f..8e0dd81 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00001.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00002.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00002.9.png
index 479a26e..8a4c259 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00002.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00003.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00003.9.png
index 77d3130..20b85e8 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00003.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00004.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00004.9.png
index cfe684f..f020081 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00004.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00005.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00005.9.png
index 4a64a36..97d6578 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00005.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00006.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00006.9.png
index 29591ff..df35ee7 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00006.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00007.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00007.9.png
index cf7cf49..29674d9 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00007.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00008.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00008.9.png
index 2a2a9af..ab2f657 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00008.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00009.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00009.9.png
index 1f7fe5f..8f53966 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00009.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00010.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00010.9.png
index f5d7093..349dbca 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00010.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00011.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00011.9.png
index 3878386..e6a3276 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00011.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00012.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00012.9.png
index adcb9e9..45273ab 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00012.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off.9.png b/core/res/res/drawable-hdpi/btn_toggle_off.9.png
index 9e141d8..08d232a 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_off.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_off.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_disabled_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_disabled_focused_holo_dark.9.png
index c5c0e97..a4b3d0a 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_off_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_disabled_focused_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_disabled_focused_holo_light.9.png
index c5c0e97..a4b3d0a 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_off_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_disabled_holo_dark.9.png
index 3b31225..58a2133 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_off_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_disabled_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_disabled_holo_light.9.png
index 3b31225..58a2133 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_off_disabled_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_focused_holo_dark.9.png
index b65009e..0c9a1e3 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_off_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_focused_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_focused_holo_light.9.png
index b65009e..0c9a1e3 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_off_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_normal_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_normal_holo_dark.9.png
index a2dfcae..0230736 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_off_normal_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_normal_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_normal_holo_light.9.png
index c3fda0e..547a60a 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_off_normal_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_pressed_holo_dark.9.png
index 94c0ee7..99b7e37 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_off_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_pressed_holo_light.9.png
index 9bef909..833b606 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_off_pressed_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on.9.png b/core/res/res/drawable-hdpi/btn_toggle_on.9.png
index dba2fa5..d02670e 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_on.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_on.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_disabled_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_disabled_focused_holo_dark.9.png
index bae60a7..9938126 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_on_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_disabled_focused_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_disabled_focused_holo_light.9.png
index bae60a7..9938126 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_on_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_disabled_holo_dark.9.png
index a9653b0..1c91d6a 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_on_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_disabled_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_disabled_holo_light.9.png
index a9653b0..1c91d6a 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_on_disabled_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_focused_holo_dark.9.png
index 394cb5e..44dd942 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_on_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_focused_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_focused_holo_light.9.png
index 394cb5e..44dd942 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_on_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_normal_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_normal_holo_dark.9.png
index aa23c6e..89d2d27 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_on_normal_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_normal_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_normal_holo_light.9.png
index 028b3b8..d2512ee 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_on_normal_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_pressed_holo_dark.9.png
index 469ba9b..35bb174 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_on_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_pressed_holo_light.9.png
index 40a61ca..ba982f2 100644
--- a/core/res/res/drawable-hdpi/btn_toggle_on_pressed_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_zoom_down_disabled.9.png b/core/res/res/drawable-hdpi/btn_zoom_down_disabled.9.png
index 6441f4d..4f1abe3 100644
--- a/core/res/res/drawable-hdpi/btn_zoom_down_disabled.9.png
+++ b/core/res/res/drawable-hdpi/btn_zoom_down_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_zoom_down_disabled_focused.9.png b/core/res/res/drawable-hdpi/btn_zoom_down_disabled_focused.9.png
index cfb0613..701aff7 100644
--- a/core/res/res/drawable-hdpi/btn_zoom_down_disabled_focused.9.png
+++ b/core/res/res/drawable-hdpi/btn_zoom_down_disabled_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_zoom_down_normal.9.png b/core/res/res/drawable-hdpi/btn_zoom_down_normal.9.png
index b30f834..6336e3a 100644
--- a/core/res/res/drawable-hdpi/btn_zoom_down_normal.9.png
+++ b/core/res/res/drawable-hdpi/btn_zoom_down_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_zoom_down_pressed.9.png b/core/res/res/drawable-hdpi/btn_zoom_down_pressed.9.png
index 4ff9910..91db982 100644
--- a/core/res/res/drawable-hdpi/btn_zoom_down_pressed.9.png
+++ b/core/res/res/drawable-hdpi/btn_zoom_down_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_zoom_down_selected.9.png b/core/res/res/drawable-hdpi/btn_zoom_down_selected.9.png
index 5542695..b208775 100644
--- a/core/res/res/drawable-hdpi/btn_zoom_down_selected.9.png
+++ b/core/res/res/drawable-hdpi/btn_zoom_down_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_zoom_page_normal.png b/core/res/res/drawable-hdpi/btn_zoom_page_normal.png
index 15d60a0..971a885 100644
--- a/core/res/res/drawable-hdpi/btn_zoom_page_normal.png
+++ b/core/res/res/drawable-hdpi/btn_zoom_page_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_zoom_page_press.png b/core/res/res/drawable-hdpi/btn_zoom_page_press.png
index 28f437e..4cb9bf8 100644
--- a/core/res/res/drawable-hdpi/btn_zoom_page_press.png
+++ b/core/res/res/drawable-hdpi/btn_zoom_page_press.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_zoom_up_disabled.9.png b/core/res/res/drawable-hdpi/btn_zoom_up_disabled.9.png
index 6a55903..2923cea 100644
--- a/core/res/res/drawable-hdpi/btn_zoom_up_disabled.9.png
+++ b/core/res/res/drawable-hdpi/btn_zoom_up_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_zoom_up_disabled_focused.9.png b/core/res/res/drawable-hdpi/btn_zoom_up_disabled_focused.9.png
index 7adbae1..41bb548 100644
--- a/core/res/res/drawable-hdpi/btn_zoom_up_disabled_focused.9.png
+++ b/core/res/res/drawable-hdpi/btn_zoom_up_disabled_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_zoom_up_normal.9.png b/core/res/res/drawable-hdpi/btn_zoom_up_normal.9.png
index 4631a32..2223b6d 100644
--- a/core/res/res/drawable-hdpi/btn_zoom_up_normal.9.png
+++ b/core/res/res/drawable-hdpi/btn_zoom_up_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_zoom_up_pressed.9.png b/core/res/res/drawable-hdpi/btn_zoom_up_pressed.9.png
index df75fec..cfe0832 100644
--- a/core/res/res/drawable-hdpi/btn_zoom_up_pressed.9.png
+++ b/core/res/res/drawable-hdpi/btn_zoom_up_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_zoom_up_selected.9.png b/core/res/res/drawable-hdpi/btn_zoom_up_selected.9.png
index bae522c..c1293f5 100644
--- a/core/res/res/drawable-hdpi/btn_zoom_up_selected.9.png
+++ b/core/res/res/drawable-hdpi/btn_zoom_up_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/button_onoff_indicator_off.png b/core/res/res/drawable-hdpi/button_onoff_indicator_off.png
index 9af36e9..ad876d9 100644
--- a/core/res/res/drawable-hdpi/button_onoff_indicator_off.png
+++ b/core/res/res/drawable-hdpi/button_onoff_indicator_off.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/button_onoff_indicator_on.png b/core/res/res/drawable-hdpi/button_onoff_indicator_on.png
index bde297e..464597e 100644
--- a/core/res/res/drawable-hdpi/button_onoff_indicator_on.png
+++ b/core/res/res/drawable-hdpi/button_onoff_indicator_on.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/cab_background_bottom_holo_dark.9.png b/core/res/res/drawable-hdpi/cab_background_bottom_holo_dark.9.png
index 1d836f6..a4cf516 100644
--- a/core/res/res/drawable-hdpi/cab_background_bottom_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/cab_background_bottom_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/cab_background_bottom_holo_light.9.png b/core/res/res/drawable-hdpi/cab_background_bottom_holo_light.9.png
index 5818666..5c6d577 100644
--- a/core/res/res/drawable-hdpi/cab_background_bottom_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/cab_background_bottom_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/cab_background_bottom_mtrl_alpha.9.png b/core/res/res/drawable-hdpi/cab_background_bottom_mtrl_alpha.9.png
index 92613b7..d2b8a11 100644
--- a/core/res/res/drawable-hdpi/cab_background_bottom_mtrl_alpha.9.png
+++ b/core/res/res/drawable-hdpi/cab_background_bottom_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/cab_background_top_holo_dark.9.png b/core/res/res/drawable-hdpi/cab_background_top_holo_dark.9.png
index 564fb34..843d27bfa 100644
--- a/core/res/res/drawable-hdpi/cab_background_top_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/cab_background_top_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/cab_background_top_holo_light.9.png b/core/res/res/drawable-hdpi/cab_background_top_holo_light.9.png
index ae21b76..94fec9d 100644
--- a/core/res/res/drawable-hdpi/cab_background_top_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/cab_background_top_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/cab_background_top_mtrl_alpha.9.png b/core/res/res/drawable-hdpi/cab_background_top_mtrl_alpha.9.png
index e51ef280..f94ec5d 100644
--- a/core/res/res/drawable-hdpi/cab_background_top_mtrl_alpha.9.png
+++ b/core/res/res/drawable-hdpi/cab_background_top_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/call_contact.png b/core/res/res/drawable-hdpi/call_contact.png
index 57fea24..c0bd1c6 100644
--- a/core/res/res/drawable-hdpi/call_contact.png
+++ b/core/res/res/drawable-hdpi/call_contact.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/checkbox_off_background.png b/core/res/res/drawable-hdpi/checkbox_off_background.png
index a8e4785..46594a7 100644
--- a/core/res/res/drawable-hdpi/checkbox_off_background.png
+++ b/core/res/res/drawable-hdpi/checkbox_off_background.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/checkbox_on_background.png b/core/res/res/drawable-hdpi/checkbox_on_background.png
index 800d3d5..327ce3a 100644
--- a/core/res/res/drawable-hdpi/checkbox_on_background.png
+++ b/core/res/res/drawable-hdpi/checkbox_on_background.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/cling_arrow_up.png b/core/res/res/drawable-hdpi/cling_arrow_up.png
index 8ef2050..929efbe 100644
--- a/core/res/res/drawable-hdpi/cling_arrow_up.png
+++ b/core/res/res/drawable-hdpi/cling_arrow_up.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/cling_bg.9.png b/core/res/res/drawable-hdpi/cling_bg.9.png
index 36fbfc8..6f76a2b 100644
--- a/core/res/res/drawable-hdpi/cling_bg.9.png
+++ b/core/res/res/drawable-hdpi/cling_bg.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/cling_button_normal.9.png b/core/res/res/drawable-hdpi/cling_button_normal.9.png
index e308382..c043288 100644
--- a/core/res/res/drawable-hdpi/cling_button_normal.9.png
+++ b/core/res/res/drawable-hdpi/cling_button_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/cling_button_pressed.9.png b/core/res/res/drawable-hdpi/cling_button_pressed.9.png
index 4f9ca6f..192c59c 100644
--- a/core/res/res/drawable-hdpi/cling_button_pressed.9.png
+++ b/core/res/res/drawable-hdpi/cling_button_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/code_lock_bottom.9.png b/core/res/res/drawable-hdpi/code_lock_bottom.9.png
index e72d0f7..5c0eced 100644
--- a/core/res/res/drawable-hdpi/code_lock_bottom.9.png
+++ b/core/res/res/drawable-hdpi/code_lock_bottom.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/code_lock_left.9.png b/core/res/res/drawable-hdpi/code_lock_left.9.png
index 76ff1f5..68ec100 100644
--- a/core/res/res/drawable-hdpi/code_lock_left.9.png
+++ b/core/res/res/drawable-hdpi/code_lock_left.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/code_lock_top.9.png b/core/res/res/drawable-hdpi/code_lock_top.9.png
index 20af255..b5c2765 100644
--- a/core/res/res/drawable-hdpi/code_lock_top.9.png
+++ b/core/res/res/drawable-hdpi/code_lock_top.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/combobox_disabled.png b/core/res/res/drawable-hdpi/combobox_disabled.png
index 85fbc3c..239ad4c 100644
--- a/core/res/res/drawable-hdpi/combobox_disabled.png
+++ b/core/res/res/drawable-hdpi/combobox_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/combobox_nohighlight.png b/core/res/res/drawable-hdpi/combobox_nohighlight.png
index 2de2abb..87f3edc 100644
--- a/core/res/res/drawable-hdpi/combobox_nohighlight.png
+++ b/core/res/res/drawable-hdpi/combobox_nohighlight.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/compass_arrow.png b/core/res/res/drawable-hdpi/compass_arrow.png
index 6dbd900..071e761 100644
--- a/core/res/res/drawable-hdpi/compass_arrow.png
+++ b/core/res/res/drawable-hdpi/compass_arrow.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/compass_base.png b/core/res/res/drawable-hdpi/compass_base.png
index 298fc09..9eb58a9 100644
--- a/core/res/res/drawable-hdpi/compass_base.png
+++ b/core/res/res/drawable-hdpi/compass_base.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/contact_header_bg.9.png b/core/res/res/drawable-hdpi/contact_header_bg.9.png
index 981b2e9..38ee42d 100644
--- a/core/res/res/drawable-hdpi/contact_header_bg.9.png
+++ b/core/res/res/drawable-hdpi/contact_header_bg.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/create_contact.png b/core/res/res/drawable-hdpi/create_contact.png
index 7a29b65..3635648 100644
--- a/core/res/res/drawable-hdpi/create_contact.png
+++ b/core/res/res/drawable-hdpi/create_contact.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dark_header.9.png b/core/res/res/drawable-hdpi/dark_header.9.png
index 8cd231b..1c5c951 100644
--- a/core/res/res/drawable-hdpi/dark_header.9.png
+++ b/core/res/res/drawable-hdpi/dark_header.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/day_picker_week_view_dayline_holo.9.png b/core/res/res/drawable-hdpi/day_picker_week_view_dayline_holo.9.png
index 1deaad7..8686898 100644
--- a/core/res/res/drawable-hdpi/day_picker_week_view_dayline_holo.9.png
+++ b/core/res/res/drawable-hdpi/day_picker_week_view_dayline_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_bottom_holo_dark.9.png b/core/res/res/drawable-hdpi/dialog_bottom_holo_dark.9.png
index b23740c..24b75aa 100644
--- a/core/res/res/drawable-hdpi/dialog_bottom_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/dialog_bottom_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_bottom_holo_light.9.png b/core/res/res/drawable-hdpi/dialog_bottom_holo_light.9.png
index 44803d7..86c4503 100644
--- a/core/res/res/drawable-hdpi/dialog_bottom_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/dialog_bottom_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_divider_horizontal_holo_dark.9.png b/core/res/res/drawable-hdpi/dialog_divider_horizontal_holo_dark.9.png
index 77b0999..05017da 100644
--- a/core/res/res/drawable-hdpi/dialog_divider_horizontal_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/dialog_divider_horizontal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_divider_horizontal_holo_light.9.png b/core/res/res/drawable-hdpi/dialog_divider_horizontal_holo_light.9.png
index 3fde76e..495f26b 100644
--- a/core/res/res/drawable-hdpi/dialog_divider_horizontal_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/dialog_divider_horizontal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_divider_horizontal_light.9.png b/core/res/res/drawable-hdpi/dialog_divider_horizontal_light.9.png
index 441ef32..aae8c5d 100644
--- a/core/res/res/drawable-hdpi/dialog_divider_horizontal_light.9.png
+++ b/core/res/res/drawable-hdpi/dialog_divider_horizontal_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_full_holo_dark.9.png b/core/res/res/drawable-hdpi/dialog_full_holo_dark.9.png
index 911f3fe..2edc932 100644
--- a/core/res/res/drawable-hdpi/dialog_full_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/dialog_full_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_full_holo_light.9.png b/core/res/res/drawable-hdpi/dialog_full_holo_light.9.png
index 2129567..053e0c8 100644
--- a/core/res/res/drawable-hdpi/dialog_full_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/dialog_full_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_ic_close_focused_holo_dark.png b/core/res/res/drawable-hdpi/dialog_ic_close_focused_holo_dark.png
index 0b67f24..14448c3 100644
--- a/core/res/res/drawable-hdpi/dialog_ic_close_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/dialog_ic_close_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_ic_close_focused_holo_light.png b/core/res/res/drawable-hdpi/dialog_ic_close_focused_holo_light.png
index 107ffe4..edbb198 100644
--- a/core/res/res/drawable-hdpi/dialog_ic_close_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/dialog_ic_close_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_ic_close_normal_holo_dark.png b/core/res/res/drawable-hdpi/dialog_ic_close_normal_holo_dark.png
index 2711284..785b13d 100644
--- a/core/res/res/drawable-hdpi/dialog_ic_close_normal_holo_dark.png
+++ b/core/res/res/drawable-hdpi/dialog_ic_close_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_ic_close_normal_holo_light.png b/core/res/res/drawable-hdpi/dialog_ic_close_normal_holo_light.png
index 1aca4b7..f5afbf8 100644
--- a/core/res/res/drawable-hdpi/dialog_ic_close_normal_holo_light.png
+++ b/core/res/res/drawable-hdpi/dialog_ic_close_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_ic_close_pressed_holo_dark.png b/core/res/res/drawable-hdpi/dialog_ic_close_pressed_holo_dark.png
index 9e06c00..95747dd 100644
--- a/core/res/res/drawable-hdpi/dialog_ic_close_pressed_holo_dark.png
+++ b/core/res/res/drawable-hdpi/dialog_ic_close_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_ic_close_pressed_holo_light.png b/core/res/res/drawable-hdpi/dialog_ic_close_pressed_holo_light.png
index f032510..5b9f2da 100644
--- a/core/res/res/drawable-hdpi/dialog_ic_close_pressed_holo_light.png
+++ b/core/res/res/drawable-hdpi/dialog_ic_close_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_middle_holo.9.png b/core/res/res/drawable-hdpi/dialog_middle_holo.9.png
index dc5e79d..9a2fda63 100644
--- a/core/res/res/drawable-hdpi/dialog_middle_holo.9.png
+++ b/core/res/res/drawable-hdpi/dialog_middle_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_middle_holo_dark.9.png b/core/res/res/drawable-hdpi/dialog_middle_holo_dark.9.png
index 9ce7cfc..479aaaa 100644
--- a/core/res/res/drawable-hdpi/dialog_middle_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/dialog_middle_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_middle_holo_light.9.png b/core/res/res/drawable-hdpi/dialog_middle_holo_light.9.png
index 396a0f2..dadc076 100644
--- a/core/res/res/drawable-hdpi/dialog_middle_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/dialog_middle_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_top_holo_dark.9.png b/core/res/res/drawable-hdpi/dialog_top_holo_dark.9.png
index 22ca61f..1f09395 100644
--- a/core/res/res/drawable-hdpi/dialog_top_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/dialog_top_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_top_holo_light.9.png b/core/res/res/drawable-hdpi/dialog_top_holo_light.9.png
index 9b54cd5..443c2aa 100644
--- a/core/res/res/drawable-hdpi/dialog_top_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/dialog_top_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/divider_horizontal_bright.9.png b/core/res/res/drawable-hdpi/divider_horizontal_bright.9.png
index 41b776b..f355428 100644
--- a/core/res/res/drawable-hdpi/divider_horizontal_bright.9.png
+++ b/core/res/res/drawable-hdpi/divider_horizontal_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/divider_horizontal_bright_opaque.9.png b/core/res/res/drawable-hdpi/divider_horizontal_bright_opaque.9.png
index eb75a22..72909ae 100644
--- a/core/res/res/drawable-hdpi/divider_horizontal_bright_opaque.9.png
+++ b/core/res/res/drawable-hdpi/divider_horizontal_bright_opaque.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/divider_horizontal_dark.9.png b/core/res/res/drawable-hdpi/divider_horizontal_dark.9.png
index 55a5e53..87769d6 100644
--- a/core/res/res/drawable-hdpi/divider_horizontal_dark.9.png
+++ b/core/res/res/drawable-hdpi/divider_horizontal_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/divider_horizontal_dark_opaque.9.png b/core/res/res/drawable-hdpi/divider_horizontal_dark_opaque.9.png
index 60e2cb2..12ff35d 100644
--- a/core/res/res/drawable-hdpi/divider_horizontal_dark_opaque.9.png
+++ b/core/res/res/drawable-hdpi/divider_horizontal_dark_opaque.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/divider_horizontal_dim_dark.9.png b/core/res/res/drawable-hdpi/divider_horizontal_dim_dark.9.png
index cf34613..91c18c1 100644
--- a/core/res/res/drawable-hdpi/divider_horizontal_dim_dark.9.png
+++ b/core/res/res/drawable-hdpi/divider_horizontal_dim_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/divider_horizontal_holo_dark.9.png b/core/res/res/drawable-hdpi/divider_horizontal_holo_dark.9.png
index 3dfe6c2..3ee501c 100644
--- a/core/res/res/drawable-hdpi/divider_horizontal_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/divider_horizontal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/divider_horizontal_holo_light.9.png b/core/res/res/drawable-hdpi/divider_horizontal_holo_light.9.png
index ea38ebb..02007cf 100644
--- a/core/res/res/drawable-hdpi/divider_horizontal_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/divider_horizontal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/divider_horizontal_textfield.9.png b/core/res/res/drawable-hdpi/divider_horizontal_textfield.9.png
index 23b0b51..dbc660a 100644
--- a/core/res/res/drawable-hdpi/divider_horizontal_textfield.9.png
+++ b/core/res/res/drawable-hdpi/divider_horizontal_textfield.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/divider_strong_holo.9.png b/core/res/res/drawable-hdpi/divider_strong_holo.9.png
index 0758593..f107df4 100644
--- a/core/res/res/drawable-hdpi/divider_strong_holo.9.png
+++ b/core/res/res/drawable-hdpi/divider_strong_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/divider_vertical_bright.9.png b/core/res/res/drawable-hdpi/divider_vertical_bright.9.png
index 41b776b..f355428 100644
--- a/core/res/res/drawable-hdpi/divider_vertical_bright.9.png
+++ b/core/res/res/drawable-hdpi/divider_vertical_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/divider_vertical_bright_opaque.9.png b/core/res/res/drawable-hdpi/divider_vertical_bright_opaque.9.png
index eb75a22..08bc1fc 100644
--- a/core/res/res/drawable-hdpi/divider_vertical_bright_opaque.9.png
+++ b/core/res/res/drawable-hdpi/divider_vertical_bright_opaque.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/divider_vertical_dark.9.png b/core/res/res/drawable-hdpi/divider_vertical_dark.9.png
index 55a5e53..87769d6 100644
--- a/core/res/res/drawable-hdpi/divider_vertical_dark.9.png
+++ b/core/res/res/drawable-hdpi/divider_vertical_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/divider_vertical_dark_opaque.9.png b/core/res/res/drawable-hdpi/divider_vertical_dark_opaque.9.png
index 60e2cb2..7e34600 100644
--- a/core/res/res/drawable-hdpi/divider_vertical_dark_opaque.9.png
+++ b/core/res/res/drawable-hdpi/divider_vertical_dark_opaque.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/divider_vertical_holo_dark.9.png b/core/res/res/drawable-hdpi/divider_vertical_holo_dark.9.png
index c039428..7e28b00 100644
--- a/core/res/res/drawable-hdpi/divider_vertical_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/divider_vertical_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/divider_vertical_holo_light.9.png b/core/res/res/drawable-hdpi/divider_vertical_holo_light.9.png
index 7c4a29f..2dc0ba4 100644
--- a/core/res/res/drawable-hdpi/divider_vertical_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/divider_vertical_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dropdown_disabled_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/dropdown_disabled_focused_holo_dark.9.png
index 519f522..130a69a 100644
--- a/core/res/res/drawable-hdpi/dropdown_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/dropdown_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dropdown_disabled_focused_holo_light.9.png b/core/res/res/drawable-hdpi/dropdown_disabled_focused_holo_light.9.png
index 9c181d0..6caf7fc 100644
--- a/core/res/res/drawable-hdpi/dropdown_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/dropdown_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dropdown_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/dropdown_disabled_holo_dark.9.png
index 6ca975f..ad74564 100644
--- a/core/res/res/drawable-hdpi/dropdown_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/dropdown_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dropdown_disabled_holo_light.9.png b/core/res/res/drawable-hdpi/dropdown_disabled_holo_light.9.png
index 7a20af7..5ee6588 100644
--- a/core/res/res/drawable-hdpi/dropdown_disabled_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/dropdown_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dropdown_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/dropdown_focused_holo_dark.9.png
index a3dfb98..f71187a 100644
--- a/core/res/res/drawable-hdpi/dropdown_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/dropdown_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dropdown_focused_holo_light.9.png b/core/res/res/drawable-hdpi/dropdown_focused_holo_light.9.png
index 766543c..7d4a9d0 100644
--- a/core/res/res/drawable-hdpi/dropdown_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/dropdown_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dropdown_ic_arrow_disabled_focused_holo_dark.png b/core/res/res/drawable-hdpi/dropdown_ic_arrow_disabled_focused_holo_dark.png
index 53f02576..5eafd53 100644
--- a/core/res/res/drawable-hdpi/dropdown_ic_arrow_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/dropdown_ic_arrow_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dropdown_ic_arrow_disabled_focused_holo_light.png b/core/res/res/drawable-hdpi/dropdown_ic_arrow_disabled_focused_holo_light.png
index 0daee9b..f13a249 100644
--- a/core/res/res/drawable-hdpi/dropdown_ic_arrow_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/dropdown_ic_arrow_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dropdown_ic_arrow_disabled_holo_dark.png b/core/res/res/drawable-hdpi/dropdown_ic_arrow_disabled_holo_dark.png
index b659926..774fe5c 100644
--- a/core/res/res/drawable-hdpi/dropdown_ic_arrow_disabled_holo_dark.png
+++ b/core/res/res/drawable-hdpi/dropdown_ic_arrow_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dropdown_ic_arrow_disabled_holo_light.png b/core/res/res/drawable-hdpi/dropdown_ic_arrow_disabled_holo_light.png
index e22dbfd..cec8683 100644
--- a/core/res/res/drawable-hdpi/dropdown_ic_arrow_disabled_holo_light.png
+++ b/core/res/res/drawable-hdpi/dropdown_ic_arrow_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dropdown_ic_arrow_focused_holo_dark.png b/core/res/res/drawable-hdpi/dropdown_ic_arrow_focused_holo_dark.png
index 0f65227..36892d202 100644
--- a/core/res/res/drawable-hdpi/dropdown_ic_arrow_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/dropdown_ic_arrow_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dropdown_ic_arrow_focused_holo_light.png b/core/res/res/drawable-hdpi/dropdown_ic_arrow_focused_holo_light.png
index 9c47d7e..e632d1e 100644
--- a/core/res/res/drawable-hdpi/dropdown_ic_arrow_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/dropdown_ic_arrow_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dropdown_ic_arrow_normal_holo_dark.png b/core/res/res/drawable-hdpi/dropdown_ic_arrow_normal_holo_dark.png
index 06e5b47..8e6fc8b 100644
--- a/core/res/res/drawable-hdpi/dropdown_ic_arrow_normal_holo_dark.png
+++ b/core/res/res/drawable-hdpi/dropdown_ic_arrow_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dropdown_ic_arrow_normal_holo_light.png b/core/res/res/drawable-hdpi/dropdown_ic_arrow_normal_holo_light.png
index d362ec1..8ce9881 100644
--- a/core/res/res/drawable-hdpi/dropdown_ic_arrow_normal_holo_light.png
+++ b/core/res/res/drawable-hdpi/dropdown_ic_arrow_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dropdown_ic_arrow_pressed_holo_dark.png b/core/res/res/drawable-hdpi/dropdown_ic_arrow_pressed_holo_dark.png
index d010995..f9fc08c 100644
--- a/core/res/res/drawable-hdpi/dropdown_ic_arrow_pressed_holo_dark.png
+++ b/core/res/res/drawable-hdpi/dropdown_ic_arrow_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dropdown_ic_arrow_pressed_holo_light.png b/core/res/res/drawable-hdpi/dropdown_ic_arrow_pressed_holo_light.png
index b95f94b..12cdd6f 100644
--- a/core/res/res/drawable-hdpi/dropdown_ic_arrow_pressed_holo_light.png
+++ b/core/res/res/drawable-hdpi/dropdown_ic_arrow_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dropdown_normal_holo_dark.9.png b/core/res/res/drawable-hdpi/dropdown_normal_holo_dark.9.png
index a4ac317..1c4e33d 100644
--- a/core/res/res/drawable-hdpi/dropdown_normal_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/dropdown_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dropdown_normal_holo_light.9.png b/core/res/res/drawable-hdpi/dropdown_normal_holo_light.9.png
index b4ab9ad..38b67cc 100644
--- a/core/res/res/drawable-hdpi/dropdown_normal_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/dropdown_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dropdown_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/dropdown_pressed_holo_dark.9.png
index f6382c8..612d6a8 100644
--- a/core/res/res/drawable-hdpi/dropdown_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/dropdown_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dropdown_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/dropdown_pressed_holo_light.9.png
index c849e2f..a779fd6 100644
--- a/core/res/res/drawable-hdpi/dropdown_pressed_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/dropdown_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/edit_query.png b/core/res/res/drawable-hdpi/edit_query.png
index d3e64b2..be9c6ed 100644
--- a/core/res/res/drawable-hdpi/edit_query.png
+++ b/core/res/res/drawable-hdpi/edit_query.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/edit_query_background_normal.9.png b/core/res/res/drawable-hdpi/edit_query_background_normal.9.png
index c083129..2dd7989 100644
--- a/core/res/res/drawable-hdpi/edit_query_background_normal.9.png
+++ b/core/res/res/drawable-hdpi/edit_query_background_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/edit_query_background_pressed.9.png b/core/res/res/drawable-hdpi/edit_query_background_pressed.9.png
index 41f3970..47f39b7 100644
--- a/core/res/res/drawable-hdpi/edit_query_background_pressed.9.png
+++ b/core/res/res/drawable-hdpi/edit_query_background_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/edit_query_background_selected.9.png b/core/res/res/drawable-hdpi/edit_query_background_selected.9.png
index 04a8d12..314e4ce 100644
--- a/core/res/res/drawable-hdpi/edit_query_background_selected.9.png
+++ b/core/res/res/drawable-hdpi/edit_query_background_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/editbox_background_focus_yellow.9.png b/core/res/res/drawable-hdpi/editbox_background_focus_yellow.9.png
index 70cd52b..d0cee7f 100644
--- a/core/res/res/drawable-hdpi/editbox_background_focus_yellow.9.png
+++ b/core/res/res/drawable-hdpi/editbox_background_focus_yellow.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/editbox_background_normal.9.png b/core/res/res/drawable-hdpi/editbox_background_normal.9.png
index ce12b3b..1976b49 100644
--- a/core/res/res/drawable-hdpi/editbox_background_normal.9.png
+++ b/core/res/res/drawable-hdpi/editbox_background_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/editbox_dropdown_background.9.png b/core/res/res/drawable-hdpi/editbox_dropdown_background.9.png
index e7967d5..d92989c 100644
--- a/core/res/res/drawable-hdpi/editbox_dropdown_background.9.png
+++ b/core/res/res/drawable-hdpi/editbox_dropdown_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/editbox_dropdown_background_dark.9.png b/core/res/res/drawable-hdpi/editbox_dropdown_background_dark.9.png
index 4cce373..27debbe 100644
--- a/core/res/res/drawable-hdpi/editbox_dropdown_background_dark.9.png
+++ b/core/res/res/drawable-hdpi/editbox_dropdown_background_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/emo_im_angel.png b/core/res/res/drawable-hdpi/emo_im_angel.png
index 2cbb7da..2031a3a 100644
--- a/core/res/res/drawable-hdpi/emo_im_angel.png
+++ b/core/res/res/drawable-hdpi/emo_im_angel.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/emo_im_cool.png b/core/res/res/drawable-hdpi/emo_im_cool.png
index 3813bc6..da7d15b 100644
--- a/core/res/res/drawable-hdpi/emo_im_cool.png
+++ b/core/res/res/drawable-hdpi/emo_im_cool.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/emo_im_crying.png b/core/res/res/drawable-hdpi/emo_im_crying.png
index 3982d70..24ce825 100644
--- a/core/res/res/drawable-hdpi/emo_im_crying.png
+++ b/core/res/res/drawable-hdpi/emo_im_crying.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/emo_im_embarrassed.png b/core/res/res/drawable-hdpi/emo_im_embarrassed.png
index 982f0ae..955f33d 100644
--- a/core/res/res/drawable-hdpi/emo_im_embarrassed.png
+++ b/core/res/res/drawable-hdpi/emo_im_embarrassed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/emo_im_foot_in_mouth.png b/core/res/res/drawable-hdpi/emo_im_foot_in_mouth.png
index d40fb90..b617b99 100644
--- a/core/res/res/drawable-hdpi/emo_im_foot_in_mouth.png
+++ b/core/res/res/drawable-hdpi/emo_im_foot_in_mouth.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/emo_im_happy.png b/core/res/res/drawable-hdpi/emo_im_happy.png
index f1e4723..f68fdab 100644
--- a/core/res/res/drawable-hdpi/emo_im_happy.png
+++ b/core/res/res/drawable-hdpi/emo_im_happy.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/emo_im_kissing.png b/core/res/res/drawable-hdpi/emo_im_kissing.png
index 21e5d30..1c4cbab 100644
--- a/core/res/res/drawable-hdpi/emo_im_kissing.png
+++ b/core/res/res/drawable-hdpi/emo_im_kissing.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/emo_im_laughing.png b/core/res/res/drawable-hdpi/emo_im_laughing.png
index 03aa60a..4c36e8c8 100644
--- a/core/res/res/drawable-hdpi/emo_im_laughing.png
+++ b/core/res/res/drawable-hdpi/emo_im_laughing.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/emo_im_lips_are_sealed.png b/core/res/res/drawable-hdpi/emo_im_lips_are_sealed.png
index 14edaeb..39bcd87 100644
--- a/core/res/res/drawable-hdpi/emo_im_lips_are_sealed.png
+++ b/core/res/res/drawable-hdpi/emo_im_lips_are_sealed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/emo_im_money_mouth.png b/core/res/res/drawable-hdpi/emo_im_money_mouth.png
index 957bc90..197f9b0 100644
--- a/core/res/res/drawable-hdpi/emo_im_money_mouth.png
+++ b/core/res/res/drawable-hdpi/emo_im_money_mouth.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/emo_im_sad.png b/core/res/res/drawable-hdpi/emo_im_sad.png
index bcfe71b4..3b757e5 100644
--- a/core/res/res/drawable-hdpi/emo_im_sad.png
+++ b/core/res/res/drawable-hdpi/emo_im_sad.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/emo_im_surprised.png b/core/res/res/drawable-hdpi/emo_im_surprised.png
index 961a9bb..c18ccdb 100644
--- a/core/res/res/drawable-hdpi/emo_im_surprised.png
+++ b/core/res/res/drawable-hdpi/emo_im_surprised.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/emo_im_tongue_sticking_out.png b/core/res/res/drawable-hdpi/emo_im_tongue_sticking_out.png
index 7a1235c..6384282 100644
--- a/core/res/res/drawable-hdpi/emo_im_tongue_sticking_out.png
+++ b/core/res/res/drawable-hdpi/emo_im_tongue_sticking_out.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/emo_im_undecided.png b/core/res/res/drawable-hdpi/emo_im_undecided.png
index 72bf2f2..35cae55 100644
--- a/core/res/res/drawable-hdpi/emo_im_undecided.png
+++ b/core/res/res/drawable-hdpi/emo_im_undecided.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/emo_im_winking.png b/core/res/res/drawable-hdpi/emo_im_winking.png
index b8fd6d9..ed94031 100644
--- a/core/res/res/drawable-hdpi/emo_im_winking.png
+++ b/core/res/res/drawable-hdpi/emo_im_winking.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/emo_im_wtf.png b/core/res/res/drawable-hdpi/emo_im_wtf.png
index b221795..f1cda2c 100644
--- a/core/res/res/drawable-hdpi/emo_im_wtf.png
+++ b/core/res/res/drawable-hdpi/emo_im_wtf.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/emo_im_yelling.png b/core/res/res/drawable-hdpi/emo_im_yelling.png
index 59798cb..fb39702 100644
--- a/core/res/res/drawable-hdpi/emo_im_yelling.png
+++ b/core/res/res/drawable-hdpi/emo_im_yelling.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/expander_close_holo_dark.9.png b/core/res/res/drawable-hdpi/expander_close_holo_dark.9.png
index 73ff79f..9ffc719 100644
--- a/core/res/res/drawable-hdpi/expander_close_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/expander_close_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/expander_close_holo_light.9.png b/core/res/res/drawable-hdpi/expander_close_holo_light.9.png
index 290c24d..64b01f6 100644
--- a/core/res/res/drawable-hdpi/expander_close_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/expander_close_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/expander_close_mtrl_alpha.9.png b/core/res/res/drawable-hdpi/expander_close_mtrl_alpha.9.png
index 7bf9d90..77294cd 100644
--- a/core/res/res/drawable-hdpi/expander_close_mtrl_alpha.9.png
+++ b/core/res/res/drawable-hdpi/expander_close_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/expander_ic_maximized.9.png b/core/res/res/drawable-hdpi/expander_ic_maximized.9.png
index 2ec27af..2d4176d 100644
--- a/core/res/res/drawable-hdpi/expander_ic_maximized.9.png
+++ b/core/res/res/drawable-hdpi/expander_ic_maximized.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/expander_ic_minimized.9.png b/core/res/res/drawable-hdpi/expander_ic_minimized.9.png
index 0c19bb7..a1ab3a9 100644
--- a/core/res/res/drawable-hdpi/expander_ic_minimized.9.png
+++ b/core/res/res/drawable-hdpi/expander_ic_minimized.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/expander_open_holo_dark.9.png b/core/res/res/drawable-hdpi/expander_open_holo_dark.9.png
index 754032e..72dfd58 100644
--- a/core/res/res/drawable-hdpi/expander_open_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/expander_open_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/expander_open_holo_light.9.png b/core/res/res/drawable-hdpi/expander_open_holo_light.9.png
index e32c7c7..8914012 100644
--- a/core/res/res/drawable-hdpi/expander_open_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/expander_open_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/expander_open_mtrl_alpha.9.png b/core/res/res/drawable-hdpi/expander_open_mtrl_alpha.9.png
index d427a20..74fe026 100644
--- a/core/res/res/drawable-hdpi/expander_open_mtrl_alpha.9.png
+++ b/core/res/res/drawable-hdpi/expander_open_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/fastscroll_label_left_holo_dark.9.png b/core/res/res/drawable-hdpi/fastscroll_label_left_holo_dark.9.png
index 769cb12..bccbd7e 100644
--- a/core/res/res/drawable-hdpi/fastscroll_label_left_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/fastscroll_label_left_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/fastscroll_label_left_holo_light.9.png b/core/res/res/drawable-hdpi/fastscroll_label_left_holo_light.9.png
index c5372a8..82a899e 100644
--- a/core/res/res/drawable-hdpi/fastscroll_label_left_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/fastscroll_label_left_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/fastscroll_label_right_holo_dark.9.png b/core/res/res/drawable-hdpi/fastscroll_label_right_holo_dark.9.png
index 1dee51b..bfdb3f3 100644
--- a/core/res/res/drawable-hdpi/fastscroll_label_right_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/fastscroll_label_right_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/fastscroll_label_right_holo_light.9.png b/core/res/res/drawable-hdpi/fastscroll_label_right_holo_light.9.png
index 3c1e25a..9917b13 100644
--- a/core/res/res/drawable-hdpi/fastscroll_label_right_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/fastscroll_label_right_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/fastscroll_thumb_default_holo.png b/core/res/res/drawable-hdpi/fastscroll_thumb_default_holo.png
index 2b7c917..f39764d 100644
--- a/core/res/res/drawable-hdpi/fastscroll_thumb_default_holo.png
+++ b/core/res/res/drawable-hdpi/fastscroll_thumb_default_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/fastscroll_thumb_pressed_holo.png b/core/res/res/drawable-hdpi/fastscroll_thumb_pressed_holo.png
index 1227e9e..2a33d62 100644
--- a/core/res/res/drawable-hdpi/fastscroll_thumb_pressed_holo.png
+++ b/core/res/res/drawable-hdpi/fastscroll_thumb_pressed_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/fastscroll_track_default_holo_dark.9.png b/core/res/res/drawable-hdpi/fastscroll_track_default_holo_dark.9.png
index 707414d..85ad9d8 100644
--- a/core/res/res/drawable-hdpi/fastscroll_track_default_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/fastscroll_track_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/fastscroll_track_default_holo_light.9.png b/core/res/res/drawable-hdpi/fastscroll_track_default_holo_light.9.png
index 707414d..85ad9d8 100644
--- a/core/res/res/drawable-hdpi/fastscroll_track_default_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/fastscroll_track_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/fastscroll_track_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/fastscroll_track_pressed_holo_dark.9.png
index 4d810dd..01768dc 100644
--- a/core/res/res/drawable-hdpi/fastscroll_track_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/fastscroll_track_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/fastscroll_track_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/fastscroll_track_pressed_holo_light.9.png
index 64fa147..34e278d 100644
--- a/core/res/res/drawable-hdpi/fastscroll_track_pressed_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/fastscroll_track_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/focused_application_background_static.png b/core/res/res/drawable-hdpi/focused_application_background_static.png
index 6872f26..fc76bd3 100644
--- a/core/res/res/drawable-hdpi/focused_application_background_static.png
+++ b/core/res/res/drawable-hdpi/focused_application_background_static.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/frame_gallery_thumb.9.png b/core/res/res/drawable-hdpi/frame_gallery_thumb.9.png
index 8edbd3f..725612a 100644
--- a/core/res/res/drawable-hdpi/frame_gallery_thumb.9.png
+++ b/core/res/res/drawable-hdpi/frame_gallery_thumb.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/frame_gallery_thumb_pressed.9.png b/core/res/res/drawable-hdpi/frame_gallery_thumb_pressed.9.png
index 986e6d5..d7d8ba0 100644
--- a/core/res/res/drawable-hdpi/frame_gallery_thumb_pressed.9.png
+++ b/core/res/res/drawable-hdpi/frame_gallery_thumb_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/frame_gallery_thumb_selected.9.png b/core/res/res/drawable-hdpi/frame_gallery_thumb_selected.9.png
index 95f3ab5..1645586 100644
--- a/core/res/res/drawable-hdpi/frame_gallery_thumb_selected.9.png
+++ b/core/res/res/drawable-hdpi/frame_gallery_thumb_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/gallery_selected_default.9.png b/core/res/res/drawable-hdpi/gallery_selected_default.9.png
index 99403aa..48d12b1 100644
--- a/core/res/res/drawable-hdpi/gallery_selected_default.9.png
+++ b/core/res/res/drawable-hdpi/gallery_selected_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/gallery_selected_focused.9.png b/core/res/res/drawable-hdpi/gallery_selected_focused.9.png
index 3aa2e17..df19d20 100644
--- a/core/res/res/drawable-hdpi/gallery_selected_focused.9.png
+++ b/core/res/res/drawable-hdpi/gallery_selected_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/gallery_selected_pressed.9.png b/core/res/res/drawable-hdpi/gallery_selected_pressed.9.png
index 8f1e752..4846d19 100644
--- a/core/res/res/drawable-hdpi/gallery_selected_pressed.9.png
+++ b/core/res/res/drawable-hdpi/gallery_selected_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/gallery_unselected_default.9.png b/core/res/res/drawable-hdpi/gallery_unselected_default.9.png
index 3d10b86..5985c5b 100644
--- a/core/res/res/drawable-hdpi/gallery_unselected_default.9.png
+++ b/core/res/res/drawable-hdpi/gallery_unselected_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/gallery_unselected_pressed.9.png b/core/res/res/drawable-hdpi/gallery_unselected_pressed.9.png
index 2fa7c46..f45c8e1 100644
--- a/core/res/res/drawable-hdpi/gallery_unselected_pressed.9.png
+++ b/core/res/res/drawable-hdpi/gallery_unselected_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/grid_selector_background_focus.9.png b/core/res/res/drawable-hdpi/grid_selector_background_focus.9.png
index be2aeed..ecadd8e 100644
--- a/core/res/res/drawable-hdpi/grid_selector_background_focus.9.png
+++ b/core/res/res/drawable-hdpi/grid_selector_background_focus.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/grid_selector_background_pressed.9.png b/core/res/res/drawable-hdpi/grid_selector_background_pressed.9.png
index 27e455a..56168b3 100644
--- a/core/res/res/drawable-hdpi/grid_selector_background_pressed.9.png
+++ b/core/res/res/drawable-hdpi/grid_selector_background_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/highlight_disabled.9.png b/core/res/res/drawable-hdpi/highlight_disabled.9.png
index 46f755d..c312bf4 100644
--- a/core/res/res/drawable-hdpi/highlight_disabled.9.png
+++ b/core/res/res/drawable-hdpi/highlight_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/highlight_pressed.9.png b/core/res/res/drawable-hdpi/highlight_pressed.9.png
index 91d7db1..8062d7c 100644
--- a/core/res/res/drawable-hdpi/highlight_pressed.9.png
+++ b/core/res/res/drawable-hdpi/highlight_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/highlight_selected.9.png b/core/res/res/drawable-hdpi/highlight_selected.9.png
index 6e92dd5..7620653 100644
--- a/core/res/res/drawable-hdpi/highlight_selected.9.png
+++ b/core/res/res/drawable-hdpi/highlight_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_ab_back_holo_dark_am.png b/core/res/res/drawable-hdpi/ic_ab_back_holo_dark_am.png
index 897a1c1..25feb1f 100644
--- a/core/res/res/drawable-hdpi/ic_ab_back_holo_dark_am.png
+++ b/core/res/res/drawable-hdpi/ic_ab_back_holo_dark_am.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_ab_back_holo_light_am.png b/core/res/res/drawable-hdpi/ic_ab_back_holo_light_am.png
index 0c89f71..0e659fd 100644
--- a/core/res/res/drawable-hdpi/ic_ab_back_holo_light_am.png
+++ b/core/res/res/drawable-hdpi/ic_ab_back_holo_light_am.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_action_assist_focused.png b/core/res/res/drawable-hdpi/ic_action_assist_focused.png
index d98557d..494443a 100644
--- a/core/res/res/drawable-hdpi/ic_action_assist_focused.png
+++ b/core/res/res/drawable-hdpi/ic_action_assist_focused.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_aggregated.png b/core/res/res/drawable-hdpi/ic_aggregated.png
index b9cfc7e..03d92b2 100644
--- a/core/res/res/drawable-hdpi/ic_aggregated.png
+++ b/core/res/res/drawable-hdpi/ic_aggregated.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_audio_notification_am_alpha.png b/core/res/res/drawable-hdpi/ic_audio_notification_am_alpha.png
index 00e8f8a..b45d8d4 100644
--- a/core/res/res/drawable-hdpi/ic_audio_notification_am_alpha.png
+++ b/core/res/res/drawable-hdpi/ic_audio_notification_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_audio_notification_mute_am_alpha.png b/core/res/res/drawable-hdpi/ic_audio_notification_mute_am_alpha.png
index 697cc92..d7de8fd 100644
--- a/core/res/res/drawable-hdpi/ic_audio_notification_mute_am_alpha.png
+++ b/core/res/res/drawable-hdpi/ic_audio_notification_mute_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_btn_round_more_disabled.png b/core/res/res/drawable-hdpi/ic_btn_round_more_disabled.png
index 3f1176f..f008310 100644
--- a/core/res/res/drawable-hdpi/ic_btn_round_more_disabled.png
+++ b/core/res/res/drawable-hdpi/ic_btn_round_more_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_btn_round_more_normal.png b/core/res/res/drawable-hdpi/ic_btn_round_more_normal.png
index 8abda4d..24acf06e 100644
--- a/core/res/res/drawable-hdpi/ic_btn_round_more_normal.png
+++ b/core/res/res/drawable-hdpi/ic_btn_round_more_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_btn_search_go.png b/core/res/res/drawable-hdpi/ic_btn_search_go.png
index 65f8079..88119a3 100644
--- a/core/res/res/drawable-hdpi/ic_btn_search_go.png
+++ b/core/res/res/drawable-hdpi/ic_btn_search_go.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_btn_speak_now.png b/core/res/res/drawable-hdpi/ic_btn_speak_now.png
index c9281d3..99d0203 100644
--- a/core/res/res/drawable-hdpi/ic_btn_speak_now.png
+++ b/core/res/res/drawable-hdpi/ic_btn_speak_now.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_btn_square_browser_zoom_fit_page_disabled.png b/core/res/res/drawable-hdpi/ic_btn_square_browser_zoom_fit_page_disabled.png
index 19fe4d4..add1c22 100644
--- a/core/res/res/drawable-hdpi/ic_btn_square_browser_zoom_fit_page_disabled.png
+++ b/core/res/res/drawable-hdpi/ic_btn_square_browser_zoom_fit_page_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_btn_square_browser_zoom_fit_page_normal.png b/core/res/res/drawable-hdpi/ic_btn_square_browser_zoom_fit_page_normal.png
index c5a0594..5185f06 100644
--- a/core/res/res/drawable-hdpi/ic_btn_square_browser_zoom_fit_page_normal.png
+++ b/core/res/res/drawable-hdpi/ic_btn_square_browser_zoom_fit_page_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_btn_square_browser_zoom_page_overview_disabled.png b/core/res/res/drawable-hdpi/ic_btn_square_browser_zoom_page_overview_disabled.png
index e5b22e8..93efdda 100644
--- a/core/res/res/drawable-hdpi/ic_btn_square_browser_zoom_page_overview_disabled.png
+++ b/core/res/res/drawable-hdpi/ic_btn_square_browser_zoom_page_overview_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_btn_square_browser_zoom_page_overview_normal.png b/core/res/res/drawable-hdpi/ic_btn_square_browser_zoom_page_overview_normal.png
index 0612d01..d115467 100644
--- a/core/res/res/drawable-hdpi/ic_btn_square_browser_zoom_page_overview_normal.png
+++ b/core/res/res/drawable-hdpi/ic_btn_square_browser_zoom_page_overview_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_bullet_key_permission.png b/core/res/res/drawable-hdpi/ic_bullet_key_permission.png
index 4cf50ad..16c9a84e 100644
--- a/core/res/res/drawable-hdpi/ic_bullet_key_permission.png
+++ b/core/res/res/drawable-hdpi/ic_bullet_key_permission.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_cab_done_holo.png b/core/res/res/drawable-hdpi/ic_cab_done_holo.png
index 8c4fd2b..780ff50 100644
--- a/core/res/res/drawable-hdpi/ic_cab_done_holo.png
+++ b/core/res/res/drawable-hdpi/ic_cab_done_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_cab_done_holo_dark.png b/core/res/res/drawable-hdpi/ic_cab_done_holo_dark.png
index d8662e3..beaa2a7 100644
--- a/core/res/res/drawable-hdpi/ic_cab_done_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_cab_done_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_cab_done_holo_light.png b/core/res/res/drawable-hdpi/ic_cab_done_holo_light.png
index ed03f62..f2594be 100644
--- a/core/res/res/drawable-hdpi/ic_cab_done_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_cab_done_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_cab_done_mtrl_alpha.png b/core/res/res/drawable-hdpi/ic_cab_done_mtrl_alpha.png
index 5635459..0ae992e 100644
--- a/core/res/res/drawable-hdpi/ic_cab_done_mtrl_alpha.png
+++ b/core/res/res/drawable-hdpi/ic_cab_done_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_checkmark_holo_light.png b/core/res/res/drawable-hdpi/ic_checkmark_holo_light.png
index 2c6719b..7a027c0 100644
--- a/core/res/res/drawable-hdpi/ic_checkmark_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_checkmark_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_clear_disabled.png b/core/res/res/drawable-hdpi/ic_clear_disabled.png
index d97c342..b8726e2 100644
--- a/core/res/res/drawable-hdpi/ic_clear_disabled.png
+++ b/core/res/res/drawable-hdpi/ic_clear_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_clear_mtrl_alpha.png b/core/res/res/drawable-hdpi/ic_clear_mtrl_alpha.png
index 3813563..26668cc 100644
--- a/core/res/res/drawable-hdpi/ic_clear_mtrl_alpha.png
+++ b/core/res/res/drawable-hdpi/ic_clear_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_clear_normal.png b/core/res/res/drawable-hdpi/ic_clear_normal.png
index 33ad8d4..cde43de 100644
--- a/core/res/res/drawable-hdpi/ic_clear_normal.png
+++ b/core/res/res/drawable-hdpi/ic_clear_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_clear_search_api_disabled_holo_dark.png b/core/res/res/drawable-hdpi/ic_clear_search_api_disabled_holo_dark.png
index 62ec3df..0725cf6 100644
--- a/core/res/res/drawable-hdpi/ic_clear_search_api_disabled_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_clear_search_api_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_clear_search_api_disabled_holo_light.png b/core/res/res/drawable-hdpi/ic_clear_search_api_disabled_holo_light.png
index 3edbd74..adeb684 100644
--- a/core/res/res/drawable-hdpi/ic_clear_search_api_disabled_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_clear_search_api_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_clear_search_api_holo_dark.png b/core/res/res/drawable-hdpi/ic_clear_search_api_holo_dark.png
index 9b4a1b6..48ae689 100644
--- a/core/res/res/drawable-hdpi/ic_clear_search_api_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_clear_search_api_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_clear_search_api_holo_light.png b/core/res/res/drawable-hdpi/ic_clear_search_api_holo_light.png
index 90db01b..d92e62f 100644
--- a/core/res/res/drawable-hdpi/ic_clear_search_api_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_clear_search_api_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_coins_l.png b/core/res/res/drawable-hdpi/ic_coins_l.png
index e1e3e2a..8dcb52f 100644
--- a/core/res/res/drawable-hdpi/ic_coins_l.png
+++ b/core/res/res/drawable-hdpi/ic_coins_l.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_coins_s.png b/core/res/res/drawable-hdpi/ic_coins_s.png
index 0ada1d0..ec21858 100644
--- a/core/res/res/drawable-hdpi/ic_coins_s.png
+++ b/core/res/res/drawable-hdpi/ic_coins_s.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_commit_search_api_holo_dark.png b/core/res/res/drawable-hdpi/ic_commit_search_api_holo_dark.png
index 83f36a9..8326e95 100644
--- a/core/res/res/drawable-hdpi/ic_commit_search_api_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_commit_search_api_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_commit_search_api_holo_light.png b/core/res/res/drawable-hdpi/ic_commit_search_api_holo_light.png
index a3cc21e..f8a54c1 100644
--- a/core/res/res/drawable-hdpi/ic_commit_search_api_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_commit_search_api_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_commit_search_api_mtrl_alpha.png b/core/res/res/drawable-hdpi/ic_commit_search_api_mtrl_alpha.png
index 47263ea..b22ee96 100644
--- a/core/res/res/drawable-hdpi/ic_commit_search_api_mtrl_alpha.png
+++ b/core/res/res/drawable-hdpi/ic_commit_search_api_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_contact_picture.png b/core/res/res/drawable-hdpi/ic_contact_picture.png
index 00d0ec4..ae284f7 100644
--- a/core/res/res/drawable-hdpi/ic_contact_picture.png
+++ b/core/res/res/drawable-hdpi/ic_contact_picture.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_contact_picture_2.png b/core/res/res/drawable-hdpi/ic_contact_picture_2.png
index 5e65276..3a26a72 100644
--- a/core/res/res/drawable-hdpi/ic_contact_picture_2.png
+++ b/core/res/res/drawable-hdpi/ic_contact_picture_2.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_contact_picture_3.png b/core/res/res/drawable-hdpi/ic_contact_picture_3.png
index a8ec1e1..17d2f3c 100644
--- a/core/res/res/drawable-hdpi/ic_contact_picture_3.png
+++ b/core/res/res/drawable-hdpi/ic_contact_picture_3.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_delete.png b/core/res/res/drawable-hdpi/ic_delete.png
index f3e53d7..2a83bb0 100644
--- a/core/res/res/drawable-hdpi/ic_delete.png
+++ b/core/res/res/drawable-hdpi/ic_delete.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_dialog_alert.png b/core/res/res/drawable-hdpi/ic_dialog_alert.png
index 7f905ba..777627b 100644
--- a/core/res/res/drawable-hdpi/ic_dialog_alert.png
+++ b/core/res/res/drawable-hdpi/ic_dialog_alert.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_dialog_alert_holo_dark.png b/core/res/res/drawable-hdpi/ic_dialog_alert_holo_dark.png
index f0ba889..53d8950 100644
--- a/core/res/res/drawable-hdpi/ic_dialog_alert_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_dialog_alert_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_dialog_alert_holo_light.png b/core/res/res/drawable-hdpi/ic_dialog_alert_holo_light.png
index 1374a53..e9e2207 100644
--- a/core/res/res/drawable-hdpi/ic_dialog_alert_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_dialog_alert_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_dialog_close_normal_holo.png b/core/res/res/drawable-hdpi/ic_dialog_close_normal_holo.png
index 5ee5bb8..8a572e8 100644
--- a/core/res/res/drawable-hdpi/ic_dialog_close_normal_holo.png
+++ b/core/res/res/drawable-hdpi/ic_dialog_close_normal_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_dialog_close_pressed_holo.png b/core/res/res/drawable-hdpi/ic_dialog_close_pressed_holo.png
index 792db06..e25bee6 100644
--- a/core/res/res/drawable-hdpi/ic_dialog_close_pressed_holo.png
+++ b/core/res/res/drawable-hdpi/ic_dialog_close_pressed_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_dialog_dialer.png b/core/res/res/drawable-hdpi/ic_dialog_dialer.png
index 2ded243..7f67854 100644
--- a/core/res/res/drawable-hdpi/ic_dialog_dialer.png
+++ b/core/res/res/drawable-hdpi/ic_dialog_dialer.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_dialog_email.png b/core/res/res/drawable-hdpi/ic_dialog_email.png
index faea271..5541eb1 100644
--- a/core/res/res/drawable-hdpi/ic_dialog_email.png
+++ b/core/res/res/drawable-hdpi/ic_dialog_email.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_dialog_focused_holo.png b/core/res/res/drawable-hdpi/ic_dialog_focused_holo.png
index e208575..76fc7a9 100644
--- a/core/res/res/drawable-hdpi/ic_dialog_focused_holo.png
+++ b/core/res/res/drawable-hdpi/ic_dialog_focused_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_dialog_info.png b/core/res/res/drawable-hdpi/ic_dialog_info.png
index efee1ef..1612ab6 100644
--- a/core/res/res/drawable-hdpi/ic_dialog_info.png
+++ b/core/res/res/drawable-hdpi/ic_dialog_info.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_dialog_map.png b/core/res/res/drawable-hdpi/ic_dialog_map.png
index f102b08..2652e2b 100644
--- a/core/res/res/drawable-hdpi/ic_dialog_map.png
+++ b/core/res/res/drawable-hdpi/ic_dialog_map.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_dialog_time.png b/core/res/res/drawable-hdpi/ic_dialog_time.png
index 337a43a..b76b33d 100644
--- a/core/res/res/drawable-hdpi/ic_dialog_time.png
+++ b/core/res/res/drawable-hdpi/ic_dialog_time.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_dialog_usb.png b/core/res/res/drawable-hdpi/ic_dialog_usb.png
index e69e14a..30c5d14 100644
--- a/core/res/res/drawable-hdpi/ic_dialog_usb.png
+++ b/core/res/res/drawable-hdpi/ic_dialog_usb.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_emergency.png b/core/res/res/drawable-hdpi/ic_emergency.png
index 09bcbda..e9cc5b7 100644
--- a/core/res/res/drawable-hdpi/ic_emergency.png
+++ b/core/res/res/drawable-hdpi/ic_emergency.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_find_next_holo_dark.png b/core/res/res/drawable-hdpi/ic_find_next_holo_dark.png
index 2fe4f81..34b7b55 100644
--- a/core/res/res/drawable-hdpi/ic_find_next_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_find_next_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_find_next_holo_light.png b/core/res/res/drawable-hdpi/ic_find_next_holo_light.png
index 3748169..f0dee60 100644
--- a/core/res/res/drawable-hdpi/ic_find_next_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_find_next_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_find_next_mtrl_alpha.png b/core/res/res/drawable-hdpi/ic_find_next_mtrl_alpha.png
index 6d5edac..a28b020 100644
--- a/core/res/res/drawable-hdpi/ic_find_next_mtrl_alpha.png
+++ b/core/res/res/drawable-hdpi/ic_find_next_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_find_previous_holo_dark.png b/core/res/res/drawable-hdpi/ic_find_previous_holo_dark.png
index d4e9bd1..45a4c51 100644
--- a/core/res/res/drawable-hdpi/ic_find_previous_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_find_previous_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_find_previous_holo_light.png b/core/res/res/drawable-hdpi/ic_find_previous_holo_light.png
index e4834a2..60b3069 100644
--- a/core/res/res/drawable-hdpi/ic_find_previous_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_find_previous_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_find_previous_mtrl_alpha.png b/core/res/res/drawable-hdpi/ic_find_previous_mtrl_alpha.png
index a5921af..bdffc29 100644
--- a/core/res/res/drawable-hdpi/ic_find_previous_mtrl_alpha.png
+++ b/core/res/res/drawable-hdpi/ic_find_previous_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_go.png b/core/res/res/drawable-hdpi/ic_go.png
index 97b825e..8259c11 100644
--- a/core/res/res/drawable-hdpi/ic_go.png
+++ b/core/res/res/drawable-hdpi/ic_go.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_go_search_api_holo_dark.png b/core/res/res/drawable-hdpi/ic_go_search_api_holo_dark.png
index f062bf7..71d5ef3 100644
--- a/core/res/res/drawable-hdpi/ic_go_search_api_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_go_search_api_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_go_search_api_holo_light.png b/core/res/res/drawable-hdpi/ic_go_search_api_holo_light.png
index 7e1ba2a..0fa2f12 100644
--- a/core/res/res/drawable-hdpi/ic_go_search_api_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_go_search_api_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_input_add.png b/core/res/res/drawable-hdpi/ic_input_add.png
index d26ebac..b21864f 100644
--- a/core/res/res/drawable-hdpi/ic_input_add.png
+++ b/core/res/res/drawable-hdpi/ic_input_add.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_input_delete.png b/core/res/res/drawable-hdpi/ic_input_delete.png
index 5d638bd..c7bccbe 100644
--- a/core/res/res/drawable-hdpi/ic_input_delete.png
+++ b/core/res/res/drawable-hdpi/ic_input_delete.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_input_get.png b/core/res/res/drawable-hdpi/ic_input_get.png
index e2b665a..d2c88d0 100644
--- a/core/res/res/drawable-hdpi/ic_input_get.png
+++ b/core/res/res/drawable-hdpi/ic_input_get.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_jog_dial_answer.png b/core/res/res/drawable-hdpi/ic_jog_dial_answer.png
index ca0a825..8b84daf 100644
--- a/core/res/res/drawable-hdpi/ic_jog_dial_answer.png
+++ b/core/res/res/drawable-hdpi/ic_jog_dial_answer.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_jog_dial_answer_and_end.png b/core/res/res/drawable-hdpi/ic_jog_dial_answer_and_end.png
index 82237bd..5d31f12 100644
--- a/core/res/res/drawable-hdpi/ic_jog_dial_answer_and_end.png
+++ b/core/res/res/drawable-hdpi/ic_jog_dial_answer_and_end.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_jog_dial_answer_and_hold.png b/core/res/res/drawable-hdpi/ic_jog_dial_answer_and_hold.png
index 4946ada..fd9f193 100644
--- a/core/res/res/drawable-hdpi/ic_jog_dial_answer_and_hold.png
+++ b/core/res/res/drawable-hdpi/ic_jog_dial_answer_and_hold.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_jog_dial_decline.png b/core/res/res/drawable-hdpi/ic_jog_dial_decline.png
index 006a6e4..91cd80c 100644
--- a/core/res/res/drawable-hdpi/ic_jog_dial_decline.png
+++ b/core/res/res/drawable-hdpi/ic_jog_dial_decline.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_jog_dial_sound_off.png b/core/res/res/drawable-hdpi/ic_jog_dial_sound_off.png
index d73db48..5c3f8e4 100644
--- a/core/res/res/drawable-hdpi/ic_jog_dial_sound_off.png
+++ b/core/res/res/drawable-hdpi/ic_jog_dial_sound_off.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_jog_dial_sound_on.png b/core/res/res/drawable-hdpi/ic_jog_dial_sound_on.png
index 90da6e3..83f7686 100644
--- a/core/res/res/drawable-hdpi/ic_jog_dial_sound_on.png
+++ b/core/res/res/drawable-hdpi/ic_jog_dial_sound_on.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_jog_dial_unlock.png b/core/res/res/drawable-hdpi/ic_jog_dial_unlock.png
index a9af1af..18d8fe7 100644
--- a/core/res/res/drawable-hdpi/ic_jog_dial_unlock.png
+++ b/core/res/res/drawable-hdpi/ic_jog_dial_unlock.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_jog_dial_vibrate_on.png b/core/res/res/drawable-hdpi/ic_jog_dial_vibrate_on.png
index 86caa07..80f1361 100644
--- a/core/res/res/drawable-hdpi/ic_jog_dial_vibrate_on.png
+++ b/core/res/res/drawable-hdpi/ic_jog_dial_vibrate_on.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_launcher_android.png b/core/res/res/drawable-hdpi/ic_launcher_android.png
index 8fed953..e38d36e 100644
--- a/core/res/res/drawable-hdpi/ic_launcher_android.png
+++ b/core/res/res/drawable-hdpi/ic_launcher_android.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lock_airplane_mode_alpha.png b/core/res/res/drawable-hdpi/ic_lock_airplane_mode_alpha.png
index 90c80fd..63c22d6 100644
--- a/core/res/res/drawable-hdpi/ic_lock_airplane_mode_alpha.png
+++ b/core/res/res/drawable-hdpi/ic_lock_airplane_mode_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lock_airplane_mode_off_am_alpha.png b/core/res/res/drawable-hdpi/ic_lock_airplane_mode_off_am_alpha.png
index b055894..7dacaef 100644
--- a/core/res/res/drawable-hdpi/ic_lock_airplane_mode_off_am_alpha.png
+++ b/core/res/res/drawable-hdpi/ic_lock_airplane_mode_off_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lock_idle_alarm_alpha.png b/core/res/res/drawable-hdpi/ic_lock_idle_alarm_alpha.png
index 3cadaff..0f6756d 100644
--- a/core/res/res/drawable-hdpi/ic_lock_idle_alarm_alpha.png
+++ b/core/res/res/drawable-hdpi/ic_lock_idle_alarm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lock_idle_charging.png b/core/res/res/drawable-hdpi/ic_lock_idle_charging.png
index 42572ee..037f04e4 100644
--- a/core/res/res/drawable-hdpi/ic_lock_idle_charging.png
+++ b/core/res/res/drawable-hdpi/ic_lock_idle_charging.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lock_idle_lock.png b/core/res/res/drawable-hdpi/ic_lock_idle_lock.png
index 11163d8..f6fd42a 100644
--- a/core/res/res/drawable-hdpi/ic_lock_idle_lock.png
+++ b/core/res/res/drawable-hdpi/ic_lock_idle_lock.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lock_idle_low_battery.png b/core/res/res/drawable-hdpi/ic_lock_idle_low_battery.png
index 30ff905..d72a5dc 100644
--- a/core/res/res/drawable-hdpi/ic_lock_idle_low_battery.png
+++ b/core/res/res/drawable-hdpi/ic_lock_idle_low_battery.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lock_lock_alpha.png b/core/res/res/drawable-hdpi/ic_lock_lock_alpha.png
index 6d1029c..dacbfde 100644
--- a/core/res/res/drawable-hdpi/ic_lock_lock_alpha.png
+++ b/core/res/res/drawable-hdpi/ic_lock_lock_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lock_open_wht_24dp.png b/core/res/res/drawable-hdpi/ic_lock_open_wht_24dp.png
index 4d97045..902b236 100644
--- a/core/res/res/drawable-hdpi/ic_lock_open_wht_24dp.png
+++ b/core/res/res/drawable-hdpi/ic_lock_open_wht_24dp.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lock_outline_wht_24dp.png b/core/res/res/drawable-hdpi/ic_lock_outline_wht_24dp.png
index 46fb463..ed317e0 100644
--- a/core/res/res/drawable-hdpi/ic_lock_outline_wht_24dp.png
+++ b/core/res/res/drawable-hdpi/ic_lock_outline_wht_24dp.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lock_power_off_alpha.png b/core/res/res/drawable-hdpi/ic_lock_power_off_alpha.png
index bc2dc70..146d104 100644
--- a/core/res/res/drawable-hdpi/ic_lock_power_off_alpha.png
+++ b/core/res/res/drawable-hdpi/ic_lock_power_off_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lock_ringer_off_alpha.png b/core/res/res/drawable-hdpi/ic_lock_ringer_off_alpha.png
index e7cb234..05e3054 100644
--- a/core/res/res/drawable-hdpi/ic_lock_ringer_off_alpha.png
+++ b/core/res/res/drawable-hdpi/ic_lock_ringer_off_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lock_ringer_on_alpha.png b/core/res/res/drawable-hdpi/ic_lock_ringer_on_alpha.png
index ce0cfab9..98857f2 100644
--- a/core/res/res/drawable-hdpi/ic_lock_ringer_on_alpha.png
+++ b/core/res/res/drawable-hdpi/ic_lock_ringer_on_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lock_silent_mode.png b/core/res/res/drawable-hdpi/ic_lock_silent_mode.png
index 0d4c590..3efbde4 100644
--- a/core/res/res/drawable-hdpi/ic_lock_silent_mode.png
+++ b/core/res/res/drawable-hdpi/ic_lock_silent_mode.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lock_silent_mode_off.png b/core/res/res/drawable-hdpi/ic_lock_silent_mode_off.png
index ecb7d04..98bfde4 100644
--- a/core/res/res/drawable-hdpi/ic_lock_silent_mode_off.png
+++ b/core/res/res/drawable-hdpi/ic_lock_silent_mode_off.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lock_silent_mode_vibrate.png b/core/res/res/drawable-hdpi/ic_lock_silent_mode_vibrate.png
index 4503aceb..a61295d 100644
--- a/core/res/res/drawable-hdpi/ic_lock_silent_mode_vibrate.png
+++ b/core/res/res/drawable-hdpi/ic_lock_silent_mode_vibrate.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_handle_pressed.png b/core/res/res/drawable-hdpi/ic_lockscreen_handle_pressed.png
index 58a5f16..18d8c54 100644
--- a/core/res/res/drawable-hdpi/ic_lockscreen_handle_pressed.png
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_handle_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_maps_indicator_current_position.png b/core/res/res/drawable-hdpi/ic_maps_indicator_current_position.png
index bc9160d..f050b39 100644
--- a/core/res/res/drawable-hdpi/ic_maps_indicator_current_position.png
+++ b/core/res/res/drawable-hdpi/ic_maps_indicator_current_position.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_maps_indicator_current_position_anim1.png b/core/res/res/drawable-hdpi/ic_maps_indicator_current_position_anim1.png
index d3d9339..e70fa10 100644
--- a/core/res/res/drawable-hdpi/ic_maps_indicator_current_position_anim1.png
+++ b/core/res/res/drawable-hdpi/ic_maps_indicator_current_position_anim1.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_maps_indicator_current_position_anim2.png b/core/res/res/drawable-hdpi/ic_maps_indicator_current_position_anim2.png
index e32c223..2de9acd 100644
--- a/core/res/res/drawable-hdpi/ic_maps_indicator_current_position_anim2.png
+++ b/core/res/res/drawable-hdpi/ic_maps_indicator_current_position_anim2.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_maps_indicator_current_position_anim3.png b/core/res/res/drawable-hdpi/ic_maps_indicator_current_position_anim3.png
index cf2db7c..73c2809 100644
--- a/core/res/res/drawable-hdpi/ic_maps_indicator_current_position_anim3.png
+++ b/core/res/res/drawable-hdpi/ic_maps_indicator_current_position_anim3.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_embed_play.png b/core/res/res/drawable-hdpi/ic_media_embed_play.png
index 05778c1..70a54db 100644
--- a/core/res/res/drawable-hdpi/ic_media_embed_play.png
+++ b/core/res/res/drawable-hdpi/ic_media_embed_play.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_ff.png b/core/res/res/drawable-hdpi/ic_media_ff.png
index c65956a..33d01de 100644
--- a/core/res/res/drawable-hdpi/ic_media_ff.png
+++ b/core/res/res/drawable-hdpi/ic_media_ff.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_fullscreen.png b/core/res/res/drawable-hdpi/ic_media_fullscreen.png
index ad082453..80d4d99 100644
--- a/core/res/res/drawable-hdpi/ic_media_fullscreen.png
+++ b/core/res/res/drawable-hdpi/ic_media_fullscreen.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_next.png b/core/res/res/drawable-hdpi/ic_media_next.png
index 6e27b81..165a39d 100644
--- a/core/res/res/drawable-hdpi/ic_media_next.png
+++ b/core/res/res/drawable-hdpi/ic_media_next.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_pause.png b/core/res/res/drawable-hdpi/ic_media_pause.png
index 1d465a4..4622a31 100644
--- a/core/res/res/drawable-hdpi/ic_media_pause.png
+++ b/core/res/res/drawable-hdpi/ic_media_pause.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_play.png b/core/res/res/drawable-hdpi/ic_media_play.png
index 2746d17..dd68ee2 100644
--- a/core/res/res/drawable-hdpi/ic_media_play.png
+++ b/core/res/res/drawable-hdpi/ic_media_play.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_previous.png b/core/res/res/drawable-hdpi/ic_media_previous.png
index 85b3766..eeb466a 100644
--- a/core/res/res/drawable-hdpi/ic_media_previous.png
+++ b/core/res/res/drawable-hdpi/ic_media_previous.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_rew.png b/core/res/res/drawable-hdpi/ic_media_rew.png
index a4ac181..b489f53 100644
--- a/core/res/res/drawable-hdpi/ic_media_rew.png
+++ b/core/res/res/drawable-hdpi/ic_media_rew.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_connected_light_07_mtrl.png b/core/res/res/drawable-hdpi/ic_media_route_connected_light_07_mtrl.png
index 9a970c8..a996c3a 100644
--- a/core/res/res/drawable-hdpi/ic_media_route_connected_light_07_mtrl.png
+++ b/core/res/res/drawable-hdpi/ic_media_route_connected_light_07_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_connected_light_08_mtrl.png b/core/res/res/drawable-hdpi/ic_media_route_connected_light_08_mtrl.png
index 5c71217..a892aa9 100644
--- a/core/res/res/drawable-hdpi/ic_media_route_connected_light_08_mtrl.png
+++ b/core/res/res/drawable-hdpi/ic_media_route_connected_light_08_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_connecting_dark_12_mtrl.png b/core/res/res/drawable-hdpi/ic_media_route_connecting_dark_12_mtrl.png
index c38e4be..7d1e829 100644
--- a/core/res/res/drawable-hdpi/ic_media_route_connecting_dark_12_mtrl.png
+++ b/core/res/res/drawable-hdpi/ic_media_route_connecting_dark_12_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_connecting_light_07_mtrl.png b/core/res/res/drawable-hdpi/ic_media_route_connecting_light_07_mtrl.png
index 9a970c8..a996c3a 100644
--- a/core/res/res/drawable-hdpi/ic_media_route_connecting_light_07_mtrl.png
+++ b/core/res/res/drawable-hdpi/ic_media_route_connecting_light_07_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_connecting_light_08_mtrl.png b/core/res/res/drawable-hdpi/ic_media_route_connecting_light_08_mtrl.png
index 5c71217..a892aa9 100644
--- a/core/res/res/drawable-hdpi/ic_media_route_connecting_light_08_mtrl.png
+++ b/core/res/res/drawable-hdpi/ic_media_route_connecting_light_08_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_connecting_light_13_mtrl.png b/core/res/res/drawable-hdpi/ic_media_route_connecting_light_13_mtrl.png
index 84d944d..968eba7 100644
--- a/core/res/res/drawable-hdpi/ic_media_route_connecting_light_13_mtrl.png
+++ b/core/res/res/drawable-hdpi/ic_media_route_connecting_light_13_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_connecting_light_22_mtrl.png b/core/res/res/drawable-hdpi/ic_media_route_connecting_light_22_mtrl.png
index 39f1db7..e298007 100644
--- a/core/res/res/drawable-hdpi/ic_media_route_connecting_light_22_mtrl.png
+++ b/core/res/res/drawable-hdpi/ic_media_route_connecting_light_22_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_connecting_light_24_mtrl.png b/core/res/res/drawable-hdpi/ic_media_route_connecting_light_24_mtrl.png
index 1ac9df6..6f987909 100644
--- a/core/res/res/drawable-hdpi/ic_media_route_connecting_light_24_mtrl.png
+++ b/core/res/res/drawable-hdpi/ic_media_route_connecting_light_24_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_connecting_light_25_mtrl.png b/core/res/res/drawable-hdpi/ic_media_route_connecting_light_25_mtrl.png
index 486225b..2ccf036 100644
--- a/core/res/res/drawable-hdpi/ic_media_route_connecting_light_25_mtrl.png
+++ b/core/res/res/drawable-hdpi/ic_media_route_connecting_light_25_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_disabled_holo_dark.png b/core/res/res/drawable-hdpi/ic_media_route_disabled_holo_dark.png
index e215b96..65601d6 100644
--- a/core/res/res/drawable-hdpi/ic_media_route_disabled_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_media_route_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_disabled_holo_light.png b/core/res/res/drawable-hdpi/ic_media_route_disabled_holo_light.png
index a014e91..f338842 100644
--- a/core/res/res/drawable-hdpi/ic_media_route_disabled_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_media_route_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_disabled_mtrl_alpha.png b/core/res/res/drawable-hdpi/ic_media_route_disabled_mtrl_alpha.png
index e0a2ba1..5e31a49 100644
--- a/core/res/res/drawable-hdpi/ic_media_route_disabled_mtrl_alpha.png
+++ b/core/res/res/drawable-hdpi/ic_media_route_disabled_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_off_dark_mtrl.png b/core/res/res/drawable-hdpi/ic_media_route_off_dark_mtrl.png
index 1f180ad..bfdafd0 100644
--- a/core/res/res/drawable-hdpi/ic_media_route_off_dark_mtrl.png
+++ b/core/res/res/drawable-hdpi/ic_media_route_off_dark_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_off_holo_dark.png b/core/res/res/drawable-hdpi/ic_media_route_off_holo_dark.png
index bb8bec1..c796e7a 100644
--- a/core/res/res/drawable-hdpi/ic_media_route_off_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_media_route_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_off_holo_light.png b/core/res/res/drawable-hdpi/ic_media_route_off_holo_light.png
index aa1737e..b7952f2 100644
--- a/core/res/res/drawable-hdpi/ic_media_route_off_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_media_route_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_off_light_mtrl.png b/core/res/res/drawable-hdpi/ic_media_route_off_light_mtrl.png
index 18d83e9..f20e75d 100644
--- a/core/res/res/drawable-hdpi/ic_media_route_off_light_mtrl.png
+++ b/core/res/res/drawable-hdpi/ic_media_route_off_light_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_0_holo_dark.png b/core/res/res/drawable-hdpi/ic_media_route_on_0_holo_dark.png
index 2c1434b..2700885 100644
--- a/core/res/res/drawable-hdpi/ic_media_route_on_0_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_0_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_0_holo_light.png b/core/res/res/drawable-hdpi/ic_media_route_on_0_holo_light.png
index dbdce3e..ff64c09 100644
--- a/core/res/res/drawable-hdpi/ic_media_route_on_0_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_0_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_1_holo_dark.png b/core/res/res/drawable-hdpi/ic_media_route_on_1_holo_dark.png
index 1101864..68312ce 100644
--- a/core/res/res/drawable-hdpi/ic_media_route_on_1_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_1_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_1_holo_light.png b/core/res/res/drawable-hdpi/ic_media_route_on_1_holo_light.png
index e8e90697..3f402fc 100644
--- a/core/res/res/drawable-hdpi/ic_media_route_on_1_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_1_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_2_holo_dark.png b/core/res/res/drawable-hdpi/ic_media_route_on_2_holo_dark.png
index 8595158..eb252e6 100644
--- a/core/res/res/drawable-hdpi/ic_media_route_on_2_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_2_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_2_holo_light.png b/core/res/res/drawable-hdpi/ic_media_route_on_2_holo_light.png
index 14844d4..fde7422 100644
--- a/core/res/res/drawable-hdpi/ic_media_route_on_2_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_2_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_holo_dark.png b/core/res/res/drawable-hdpi/ic_media_route_on_holo_dark.png
index 1565a29..e796ce1 100644
--- a/core/res/res/drawable-hdpi/ic_media_route_on_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_holo_light.png b/core/res/res/drawable-hdpi/ic_media_route_on_holo_light.png
index 9b8fe87..0ef8f97 100644
--- a/core/res/res/drawable-hdpi/ic_media_route_on_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_stop.png b/core/res/res/drawable-hdpi/ic_media_stop.png
index a0ff136..e646e77 100644
--- a/core/res/res/drawable-hdpi/ic_media_stop.png
+++ b/core/res/res/drawable-hdpi/ic_media_stop.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_video_poster.png b/core/res/res/drawable-hdpi/ic_media_video_poster.png
index 77b6b0e..7e771f1 100644
--- a/core/res/res/drawable-hdpi/ic_media_video_poster.png
+++ b/core/res/res/drawable-hdpi/ic_media_video_poster.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_account_list.png b/core/res/res/drawable-hdpi/ic_menu_account_list.png
index 0f17170..f7e71da 100644
--- a/core/res/res/drawable-hdpi/ic_menu_account_list.png
+++ b/core/res/res/drawable-hdpi/ic_menu_account_list.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_add.png b/core/res/res/drawable-hdpi/ic_menu_add.png
index 444e8a5..31e1a6c 100644
--- a/core/res/res/drawable-hdpi/ic_menu_add.png
+++ b/core/res/res/drawable-hdpi/ic_menu_add.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_agenda.png b/core/res/res/drawable-hdpi/ic_menu_agenda.png
index 9e08c29..32b4da8 100644
--- a/core/res/res/drawable-hdpi/ic_menu_agenda.png
+++ b/core/res/res/drawable-hdpi/ic_menu_agenda.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_allfriends.png b/core/res/res/drawable-hdpi/ic_menu_allfriends.png
index c42e96e..4185fa2 100644
--- a/core/res/res/drawable-hdpi/ic_menu_allfriends.png
+++ b/core/res/res/drawable-hdpi/ic_menu_allfriends.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_always_landscape_portrait.png b/core/res/res/drawable-hdpi/ic_menu_always_landscape_portrait.png
index be3d314..fb41d34 100644
--- a/core/res/res/drawable-hdpi/ic_menu_always_landscape_portrait.png
+++ b/core/res/res/drawable-hdpi/ic_menu_always_landscape_portrait.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_archive.png b/core/res/res/drawable-hdpi/ic_menu_archive.png
index e2d9bc1..da15025 100644
--- a/core/res/res/drawable-hdpi/ic_menu_archive.png
+++ b/core/res/res/drawable-hdpi/ic_menu_archive.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_attachment.png b/core/res/res/drawable-hdpi/ic_menu_attachment.png
index 4a37115..e77da53 100644
--- a/core/res/res/drawable-hdpi/ic_menu_attachment.png
+++ b/core/res/res/drawable-hdpi/ic_menu_attachment.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_back.png b/core/res/res/drawable-hdpi/ic_menu_back.png
index 661a4ae..65c34eb 100644
--- a/core/res/res/drawable-hdpi/ic_menu_back.png
+++ b/core/res/res/drawable-hdpi/ic_menu_back.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_block.png b/core/res/res/drawable-hdpi/ic_menu_block.png
index 826c094..08dc4c4 100644
--- a/core/res/res/drawable-hdpi/ic_menu_block.png
+++ b/core/res/res/drawable-hdpi/ic_menu_block.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_blocked_user.png b/core/res/res/drawable-hdpi/ic_menu_blocked_user.png
index 7ca5c6f..a7fa927 100644
--- a/core/res/res/drawable-hdpi/ic_menu_blocked_user.png
+++ b/core/res/res/drawable-hdpi/ic_menu_blocked_user.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_btn_add.png b/core/res/res/drawable-hdpi/ic_menu_btn_add.png
index 444e8a5..31e1a6c 100644
--- a/core/res/res/drawable-hdpi/ic_menu_btn_add.png
+++ b/core/res/res/drawable-hdpi/ic_menu_btn_add.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_call.png b/core/res/res/drawable-hdpi/ic_menu_call.png
index f28c53935..942cc84 100644
--- a/core/res/res/drawable-hdpi/ic_menu_call.png
+++ b/core/res/res/drawable-hdpi/ic_menu_call.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_camera.png b/core/res/res/drawable-hdpi/ic_menu_camera.png
index 4936d15..d8ac026 100644
--- a/core/res/res/drawable-hdpi/ic_menu_camera.png
+++ b/core/res/res/drawable-hdpi/ic_menu_camera.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_cc_am.png b/core/res/res/drawable-hdpi/ic_menu_cc_am.png
index 18b2004..6174a69 100644
--- a/core/res/res/drawable-hdpi/ic_menu_cc_am.png
+++ b/core/res/res/drawable-hdpi/ic_menu_cc_am.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_chat_dashboard.png b/core/res/res/drawable-hdpi/ic_menu_chat_dashboard.png
index 1f26180..2b2271c 100644
--- a/core/res/res/drawable-hdpi/ic_menu_chat_dashboard.png
+++ b/core/res/res/drawable-hdpi/ic_menu_chat_dashboard.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_clear_playlist.png b/core/res/res/drawable-hdpi/ic_menu_clear_playlist.png
index 84a4a5b..77d6f88 100644
--- a/core/res/res/drawable-hdpi/ic_menu_clear_playlist.png
+++ b/core/res/res/drawable-hdpi/ic_menu_clear_playlist.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_close_clear_cancel.png b/core/res/res/drawable-hdpi/ic_menu_close_clear_cancel.png
index 778c7f0..ba252a4f 100644
--- a/core/res/res/drawable-hdpi/ic_menu_close_clear_cancel.png
+++ b/core/res/res/drawable-hdpi/ic_menu_close_clear_cancel.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_compass.png b/core/res/res/drawable-hdpi/ic_menu_compass.png
index 39760f8..33c8f6b 100644
--- a/core/res/res/drawable-hdpi/ic_menu_compass.png
+++ b/core/res/res/drawable-hdpi/ic_menu_compass.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_compose.png b/core/res/res/drawable-hdpi/ic_menu_compose.png
index 1286a28..b890de8 100644
--- a/core/res/res/drawable-hdpi/ic_menu_compose.png
+++ b/core/res/res/drawable-hdpi/ic_menu_compose.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_copy.png b/core/res/res/drawable-hdpi/ic_menu_copy.png
index 5dcc3a3..adcaecc 100644
--- a/core/res/res/drawable-hdpi/ic_menu_copy.png
+++ b/core/res/res/drawable-hdpi/ic_menu_copy.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_copy_holo_dark.png b/core/res/res/drawable-hdpi/ic_menu_copy_holo_dark.png
index d37d0a3..35d2c18 100644
--- a/core/res/res/drawable-hdpi/ic_menu_copy_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_menu_copy_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_copy_holo_light.png b/core/res/res/drawable-hdpi/ic_menu_copy_holo_light.png
index 0dd8865..9be2976 100644
--- a/core/res/res/drawable-hdpi/ic_menu_copy_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_menu_copy_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_crop.png b/core/res/res/drawable-hdpi/ic_menu_crop.png
index c2fc70d..a92b47e 100644
--- a/core/res/res/drawable-hdpi/ic_menu_crop.png
+++ b/core/res/res/drawable-hdpi/ic_menu_crop.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_cut.png b/core/res/res/drawable-hdpi/ic_menu_cut.png
index 03fac98..0301b32 100644
--- a/core/res/res/drawable-hdpi/ic_menu_cut.png
+++ b/core/res/res/drawable-hdpi/ic_menu_cut.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_cut_holo_dark.png b/core/res/res/drawable-hdpi/ic_menu_cut_holo_dark.png
index 3e00747..82e761d 100644
--- a/core/res/res/drawable-hdpi/ic_menu_cut_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_menu_cut_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_cut_holo_light.png b/core/res/res/drawable-hdpi/ic_menu_cut_holo_light.png
index c760936..de3f246 100644
--- a/core/res/res/drawable-hdpi/ic_menu_cut_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_menu_cut_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_day.png b/core/res/res/drawable-hdpi/ic_menu_day.png
index 966de8b..e73545d 100644
--- a/core/res/res/drawable-hdpi/ic_menu_day.png
+++ b/core/res/res/drawable-hdpi/ic_menu_day.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_delete.png b/core/res/res/drawable-hdpi/ic_menu_delete.png
index 24d8f6a..b8d069f 100644
--- a/core/res/res/drawable-hdpi/ic_menu_delete.png
+++ b/core/res/res/drawable-hdpi/ic_menu_delete.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_directions.png b/core/res/res/drawable-hdpi/ic_menu_directions.png
index 358b249..f35ed4d 100644
--- a/core/res/res/drawable-hdpi/ic_menu_directions.png
+++ b/core/res/res/drawable-hdpi/ic_menu_directions.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_edit.png b/core/res/res/drawable-hdpi/ic_menu_edit.png
index 9bdba1b..84b339f 100644
--- a/core/res/res/drawable-hdpi/ic_menu_edit.png
+++ b/core/res/res/drawable-hdpi/ic_menu_edit.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_emoticons.png b/core/res/res/drawable-hdpi/ic_menu_emoticons.png
index 16ec4e4..19a4919 100644
--- a/core/res/res/drawable-hdpi/ic_menu_emoticons.png
+++ b/core/res/res/drawable-hdpi/ic_menu_emoticons.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_end_conversation.png b/core/res/res/drawable-hdpi/ic_menu_end_conversation.png
index c46b757..c03e0a5 100644
--- a/core/res/res/drawable-hdpi/ic_menu_end_conversation.png
+++ b/core/res/res/drawable-hdpi/ic_menu_end_conversation.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_find.png b/core/res/res/drawable-hdpi/ic_menu_find.png
index b888202..1d4642c 100644
--- a/core/res/res/drawable-hdpi/ic_menu_find.png
+++ b/core/res/res/drawable-hdpi/ic_menu_find.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_find_holo_dark.png b/core/res/res/drawable-hdpi/ic_menu_find_holo_dark.png
index b981a4d..3ab24f8 100644
--- a/core/res/res/drawable-hdpi/ic_menu_find_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_menu_find_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_find_holo_light.png b/core/res/res/drawable-hdpi/ic_menu_find_holo_light.png
index efee6df..14e4e1d 100644
--- a/core/res/res/drawable-hdpi/ic_menu_find_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_menu_find_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_find_mtrl_alpha.png b/core/res/res/drawable-hdpi/ic_menu_find_mtrl_alpha.png
index 0f9d41f..66a2651 100644
--- a/core/res/res/drawable-hdpi/ic_menu_find_mtrl_alpha.png
+++ b/core/res/res/drawable-hdpi/ic_menu_find_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_forward.png b/core/res/res/drawable-hdpi/ic_menu_forward.png
index b1b0c89..f4f6aba 100644
--- a/core/res/res/drawable-hdpi/ic_menu_forward.png
+++ b/core/res/res/drawable-hdpi/ic_menu_forward.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_friendslist.png b/core/res/res/drawable-hdpi/ic_menu_friendslist.png
index 02b4341..dcada51 100644
--- a/core/res/res/drawable-hdpi/ic_menu_friendslist.png
+++ b/core/res/res/drawable-hdpi/ic_menu_friendslist.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_gallery.png b/core/res/res/drawable-hdpi/ic_menu_gallery.png
index 1f83b9a..791fe6a 100644
--- a/core/res/res/drawable-hdpi/ic_menu_gallery.png
+++ b/core/res/res/drawable-hdpi/ic_menu_gallery.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_goto.png b/core/res/res/drawable-hdpi/ic_menu_goto.png
index ca6e835..db46359 100644
--- a/core/res/res/drawable-hdpi/ic_menu_goto.png
+++ b/core/res/res/drawable-hdpi/ic_menu_goto.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_help.png b/core/res/res/drawable-hdpi/ic_menu_help.png
index 473b372..70db898 100644
--- a/core/res/res/drawable-hdpi/ic_menu_help.png
+++ b/core/res/res/drawable-hdpi/ic_menu_help.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_help_holo_light.png b/core/res/res/drawable-hdpi/ic_menu_help_holo_light.png
index a39eff3..61eee00 100644
--- a/core/res/res/drawable-hdpi/ic_menu_help_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_menu_help_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_home.png b/core/res/res/drawable-hdpi/ic_menu_home.png
index 3baf1ca..55c69ec 100644
--- a/core/res/res/drawable-hdpi/ic_menu_home.png
+++ b/core/res/res/drawable-hdpi/ic_menu_home.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_info_details.png b/core/res/res/drawable-hdpi/ic_menu_info_details.png
index 6a7a1e9..dbef3ef 100644
--- a/core/res/res/drawable-hdpi/ic_menu_info_details.png
+++ b/core/res/res/drawable-hdpi/ic_menu_info_details.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_invite.png b/core/res/res/drawable-hdpi/ic_menu_invite.png
index ec88b99..a35e16c 100644
--- a/core/res/res/drawable-hdpi/ic_menu_invite.png
+++ b/core/res/res/drawable-hdpi/ic_menu_invite.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_login.png b/core/res/res/drawable-hdpi/ic_menu_login.png
index afa152b..4e17973 100644
--- a/core/res/res/drawable-hdpi/ic_menu_login.png
+++ b/core/res/res/drawable-hdpi/ic_menu_login.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_manage.png b/core/res/res/drawable-hdpi/ic_menu_manage.png
index 5b7080a..6c182a0 100644
--- a/core/res/res/drawable-hdpi/ic_menu_manage.png
+++ b/core/res/res/drawable-hdpi/ic_menu_manage.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_mapmode.png b/core/res/res/drawable-hdpi/ic_menu_mapmode.png
index 5ac4a02..1157cc3 100644
--- a/core/res/res/drawable-hdpi/ic_menu_mapmode.png
+++ b/core/res/res/drawable-hdpi/ic_menu_mapmode.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_mark.png b/core/res/res/drawable-hdpi/ic_menu_mark.png
index 95a3217..0a37c13 100644
--- a/core/res/res/drawable-hdpi/ic_menu_mark.png
+++ b/core/res/res/drawable-hdpi/ic_menu_mark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_month.png b/core/res/res/drawable-hdpi/ic_menu_month.png
index 99fe5c0..8dd34299 100644
--- a/core/res/res/drawable-hdpi/ic_menu_month.png
+++ b/core/res/res/drawable-hdpi/ic_menu_month.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_more.png b/core/res/res/drawable-hdpi/ic_menu_more.png
index ede8a54..67e2be6 100644
--- a/core/res/res/drawable-hdpi/ic_menu_more.png
+++ b/core/res/res/drawable-hdpi/ic_menu_more.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_moreoverflow.png b/core/res/res/drawable-hdpi/ic_menu_moreoverflow.png
index 33bb5e76..83e1835 100644
--- a/core/res/res/drawable-hdpi/ic_menu_moreoverflow.png
+++ b/core/res/res/drawable-hdpi/ic_menu_moreoverflow.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_moreoverflow_focused_holo_dark.png b/core/res/res/drawable-hdpi/ic_menu_moreoverflow_focused_holo_dark.png
index 061f80a..9f4942c 100644
--- a/core/res/res/drawable-hdpi/ic_menu_moreoverflow_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_menu_moreoverflow_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_moreoverflow_focused_holo_light.png b/core/res/res/drawable-hdpi/ic_menu_moreoverflow_focused_holo_light.png
index d818806..1bd0330 100644
--- a/core/res/res/drawable-hdpi/ic_menu_moreoverflow_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_menu_moreoverflow_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_dark.png b/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_dark.png
index 2abc458..74f75ee 100644
--- a/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_light.png b/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_light.png
index bb6aef1..8ca6738 100644
--- a/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_my_calendar.png b/core/res/res/drawable-hdpi/ic_menu_my_calendar.png
index 360a915..cf80014 100644
--- a/core/res/res/drawable-hdpi/ic_menu_my_calendar.png
+++ b/core/res/res/drawable-hdpi/ic_menu_my_calendar.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_mylocation.png b/core/res/res/drawable-hdpi/ic_menu_mylocation.png
index ba82ee0..d472f19 100644
--- a/core/res/res/drawable-hdpi/ic_menu_mylocation.png
+++ b/core/res/res/drawable-hdpi/ic_menu_mylocation.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_myplaces.png b/core/res/res/drawable-hdpi/ic_menu_myplaces.png
index ade7532..ff45e18 100644
--- a/core/res/res/drawable-hdpi/ic_menu_myplaces.png
+++ b/core/res/res/drawable-hdpi/ic_menu_myplaces.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_notifications.png b/core/res/res/drawable-hdpi/ic_menu_notifications.png
index ded4323..e9cf405 100644
--- a/core/res/res/drawable-hdpi/ic_menu_notifications.png
+++ b/core/res/res/drawable-hdpi/ic_menu_notifications.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_paste.png b/core/res/res/drawable-hdpi/ic_menu_paste.png
index c24fd86..5131727 100644
--- a/core/res/res/drawable-hdpi/ic_menu_paste.png
+++ b/core/res/res/drawable-hdpi/ic_menu_paste.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_paste_holo_dark.png b/core/res/res/drawable-hdpi/ic_menu_paste_holo_dark.png
index eb701f2..7d5a641 100644
--- a/core/res/res/drawable-hdpi/ic_menu_paste_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_menu_paste_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_paste_holo_light.png b/core/res/res/drawable-hdpi/ic_menu_paste_holo_light.png
index 886c493..d995c95 100644
--- a/core/res/res/drawable-hdpi/ic_menu_paste_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_menu_paste_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_play_clip.png b/core/res/res/drawable-hdpi/ic_menu_play_clip.png
index 2d0d2e2..d0ace56 100644
--- a/core/res/res/drawable-hdpi/ic_menu_play_clip.png
+++ b/core/res/res/drawable-hdpi/ic_menu_play_clip.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_preferences.png b/core/res/res/drawable-hdpi/ic_menu_preferences.png
index 5321f82..ca55880 100644
--- a/core/res/res/drawable-hdpi/ic_menu_preferences.png
+++ b/core/res/res/drawable-hdpi/ic_menu_preferences.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_recent_history.png b/core/res/res/drawable-hdpi/ic_menu_recent_history.png
index 4101434..ab90743 100644
--- a/core/res/res/drawable-hdpi/ic_menu_recent_history.png
+++ b/core/res/res/drawable-hdpi/ic_menu_recent_history.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_report_image.png b/core/res/res/drawable-hdpi/ic_menu_report_image.png
index 7847b7b..168fd6e 100644
--- a/core/res/res/drawable-hdpi/ic_menu_report_image.png
+++ b/core/res/res/drawable-hdpi/ic_menu_report_image.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_revert.png b/core/res/res/drawable-hdpi/ic_menu_revert.png
index 0b9cf2a..4938787 100644
--- a/core/res/res/drawable-hdpi/ic_menu_revert.png
+++ b/core/res/res/drawable-hdpi/ic_menu_revert.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_rotate.png b/core/res/res/drawable-hdpi/ic_menu_rotate.png
index 09efba4..c4dd200 100644
--- a/core/res/res/drawable-hdpi/ic_menu_rotate.png
+++ b/core/res/res/drawable-hdpi/ic_menu_rotate.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_save.png b/core/res/res/drawable-hdpi/ic_menu_save.png
index 36fc7f4..d9d1d2c 100644
--- a/core/res/res/drawable-hdpi/ic_menu_save.png
+++ b/core/res/res/drawable-hdpi/ic_menu_save.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_search.png b/core/res/res/drawable-hdpi/ic_menu_search.png
index ae2f44b..072d37f 100644
--- a/core/res/res/drawable-hdpi/ic_menu_search.png
+++ b/core/res/res/drawable-hdpi/ic_menu_search.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_search_holo_dark.png b/core/res/res/drawable-hdpi/ic_menu_search_holo_dark.png
index 420d680..61b5b51 100644
--- a/core/res/res/drawable-hdpi/ic_menu_search_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_menu_search_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_search_holo_light.png b/core/res/res/drawable-hdpi/ic_menu_search_holo_light.png
index cc661e3..5ad0b8a 100644
--- a/core/res/res/drawable-hdpi/ic_menu_search_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_menu_search_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_search_mtrl_alpha.png b/core/res/res/drawable-hdpi/ic_menu_search_mtrl_alpha.png
index f7382d3..8407266 100644
--- a/core/res/res/drawable-hdpi/ic_menu_search_mtrl_alpha.png
+++ b/core/res/res/drawable-hdpi/ic_menu_search_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_selectall_holo_dark.png b/core/res/res/drawable-hdpi/ic_menu_selectall_holo_dark.png
index c2cec7f..ca76f31 100644
--- a/core/res/res/drawable-hdpi/ic_menu_selectall_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_menu_selectall_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_selectall_holo_light.png b/core/res/res/drawable-hdpi/ic_menu_selectall_holo_light.png
index 902402e..e9ebe70 100644
--- a/core/res/res/drawable-hdpi/ic_menu_selectall_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_menu_selectall_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_send.png b/core/res/res/drawable-hdpi/ic_menu_send.png
index d94e692..7772fa2 100644
--- a/core/res/res/drawable-hdpi/ic_menu_send.png
+++ b/core/res/res/drawable-hdpi/ic_menu_send.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_set_as.png b/core/res/res/drawable-hdpi/ic_menu_set_as.png
index 41f931b..c089d2a 100644
--- a/core/res/res/drawable-hdpi/ic_menu_set_as.png
+++ b/core/res/res/drawable-hdpi/ic_menu_set_as.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_settings_holo_light.png b/core/res/res/drawable-hdpi/ic_menu_settings_holo_light.png
index 577e055..a7d811a 100644
--- a/core/res/res/drawable-hdpi/ic_menu_settings_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_menu_settings_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_share.png b/core/res/res/drawable-hdpi/ic_menu_share.png
index 2837615..ea32ee2 100644
--- a/core/res/res/drawable-hdpi/ic_menu_share.png
+++ b/core/res/res/drawable-hdpi/ic_menu_share.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_share_holo_dark.png b/core/res/res/drawable-hdpi/ic_menu_share_holo_dark.png
index 6f747c8..1e3d87a 100644
--- a/core/res/res/drawable-hdpi/ic_menu_share_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_menu_share_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_share_holo_light.png b/core/res/res/drawable-hdpi/ic_menu_share_holo_light.png
index 682b2fd..35fb5e4 100644
--- a/core/res/res/drawable-hdpi/ic_menu_share_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_menu_share_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_slideshow.png b/core/res/res/drawable-hdpi/ic_menu_slideshow.png
index b2e65b4..bf7c0ca 100644
--- a/core/res/res/drawable-hdpi/ic_menu_slideshow.png
+++ b/core/res/res/drawable-hdpi/ic_menu_slideshow.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_sort_alphabetically.png b/core/res/res/drawable-hdpi/ic_menu_sort_alphabetically.png
index 74e6b83..1d07614 100644
--- a/core/res/res/drawable-hdpi/ic_menu_sort_alphabetically.png
+++ b/core/res/res/drawable-hdpi/ic_menu_sort_alphabetically.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_sort_by_size.png b/core/res/res/drawable-hdpi/ic_menu_sort_by_size.png
index 39472a6..762c0c3 100644
--- a/core/res/res/drawable-hdpi/ic_menu_sort_by_size.png
+++ b/core/res/res/drawable-hdpi/ic_menu_sort_by_size.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_star.png b/core/res/res/drawable-hdpi/ic_menu_star.png
index 4f667a4..1816b49 100644
--- a/core/res/res/drawable-hdpi/ic_menu_star.png
+++ b/core/res/res/drawable-hdpi/ic_menu_star.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_start_conversation.png b/core/res/res/drawable-hdpi/ic_menu_start_conversation.png
index 395a5ec..97f8b46 100644
--- a/core/res/res/drawable-hdpi/ic_menu_start_conversation.png
+++ b/core/res/res/drawable-hdpi/ic_menu_start_conversation.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_stop.png b/core/res/res/drawable-hdpi/ic_menu_stop.png
index cf53a08..ca89c45 100644
--- a/core/res/res/drawable-hdpi/ic_menu_stop.png
+++ b/core/res/res/drawable-hdpi/ic_menu_stop.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_today.png b/core/res/res/drawable-hdpi/ic_menu_today.png
index b0a7a48..0a1639a 100644
--- a/core/res/res/drawable-hdpi/ic_menu_today.png
+++ b/core/res/res/drawable-hdpi/ic_menu_today.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_upload.png b/core/res/res/drawable-hdpi/ic_menu_upload.png
index a81ad20..949dc7a 100644
--- a/core/res/res/drawable-hdpi/ic_menu_upload.png
+++ b/core/res/res/drawable-hdpi/ic_menu_upload.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_upload_you_tube.png b/core/res/res/drawable-hdpi/ic_menu_upload_you_tube.png
index ce8d1b6..945990f 100644
--- a/core/res/res/drawable-hdpi/ic_menu_upload_you_tube.png
+++ b/core/res/res/drawable-hdpi/ic_menu_upload_you_tube.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_view.png b/core/res/res/drawable-hdpi/ic_menu_view.png
index 25c2ff3..aa55bca 100644
--- a/core/res/res/drawable-hdpi/ic_menu_view.png
+++ b/core/res/res/drawable-hdpi/ic_menu_view.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_week.png b/core/res/res/drawable-hdpi/ic_menu_week.png
index 69dc015..90f2a0b 100644
--- a/core/res/res/drawable-hdpi/ic_menu_week.png
+++ b/core/res/res/drawable-hdpi/ic_menu_week.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_zoom.png b/core/res/res/drawable-hdpi/ic_menu_zoom.png
index e2f56f0..d62d166 100644
--- a/core/res/res/drawable-hdpi/ic_menu_zoom.png
+++ b/core/res/res/drawable-hdpi/ic_menu_zoom.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_notification_cast_0.png b/core/res/res/drawable-hdpi/ic_notification_cast_0.png
index 74f7dc0..f9448ae 100644
--- a/core/res/res/drawable-hdpi/ic_notification_cast_0.png
+++ b/core/res/res/drawable-hdpi/ic_notification_cast_0.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_notification_cast_1.png b/core/res/res/drawable-hdpi/ic_notification_cast_1.png
index c6d267d..7493c9f 100644
--- a/core/res/res/drawable-hdpi/ic_notification_cast_1.png
+++ b/core/res/res/drawable-hdpi/ic_notification_cast_1.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_notification_cast_2.png b/core/res/res/drawable-hdpi/ic_notification_cast_2.png
index 699b299..c0dbee3 100644
--- a/core/res/res/drawable-hdpi/ic_notification_cast_2.png
+++ b/core/res/res/drawable-hdpi/ic_notification_cast_2.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_notification_clear_all.png b/core/res/res/drawable-hdpi/ic_notification_clear_all.png
index 6bff858..0e95d49 100644
--- a/core/res/res/drawable-hdpi/ic_notification_clear_all.png
+++ b/core/res/res/drawable-hdpi/ic_notification_clear_all.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_notification_overlay.9.png b/core/res/res/drawable-hdpi/ic_notification_overlay.9.png
index 744178f..342e327 100644
--- a/core/res/res/drawable-hdpi/ic_notification_overlay.9.png
+++ b/core/res/res/drawable-hdpi/ic_notification_overlay.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_partial_secure.png b/core/res/res/drawable-hdpi/ic_partial_secure.png
index 70bd08d..98dbfaf 100644
--- a/core/res/res/drawable-hdpi/ic_partial_secure.png
+++ b/core/res/res/drawable-hdpi/ic_partial_secure.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_popup_disk_full.png b/core/res/res/drawable-hdpi/ic_popup_disk_full.png
index b3c00a7..711a963 100644
--- a/core/res/res/drawable-hdpi/ic_popup_disk_full.png
+++ b/core/res/res/drawable-hdpi/ic_popup_disk_full.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_popup_reminder.png b/core/res/res/drawable-hdpi/ic_popup_reminder.png
index 9652dde..736dbaf 100644
--- a/core/res/res/drawable-hdpi/ic_popup_reminder.png
+++ b/core/res/res/drawable-hdpi/ic_popup_reminder.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_popup_sync_1.png b/core/res/res/drawable-hdpi/ic_popup_sync_1.png
index a248f59..1a6ddad 100644
--- a/core/res/res/drawable-hdpi/ic_popup_sync_1.png
+++ b/core/res/res/drawable-hdpi/ic_popup_sync_1.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_popup_sync_2.png b/core/res/res/drawable-hdpi/ic_popup_sync_2.png
index 756bfc6..4d124d7 100644
--- a/core/res/res/drawable-hdpi/ic_popup_sync_2.png
+++ b/core/res/res/drawable-hdpi/ic_popup_sync_2.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_popup_sync_3.png b/core/res/res/drawable-hdpi/ic_popup_sync_3.png
index e06825b..0972367 100644
--- a/core/res/res/drawable-hdpi/ic_popup_sync_3.png
+++ b/core/res/res/drawable-hdpi/ic_popup_sync_3.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_popup_sync_4.png b/core/res/res/drawable-hdpi/ic_popup_sync_4.png
index 87ce8f6..aee8787 100644
--- a/core/res/res/drawable-hdpi/ic_popup_sync_4.png
+++ b/core/res/res/drawable-hdpi/ic_popup_sync_4.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_popup_sync_5.png b/core/res/res/drawable-hdpi/ic_popup_sync_5.png
index 635480c..30a68a1 100644
--- a/core/res/res/drawable-hdpi/ic_popup_sync_5.png
+++ b/core/res/res/drawable-hdpi/ic_popup_sync_5.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_popup_sync_6.png b/core/res/res/drawable-hdpi/ic_popup_sync_6.png
index b339eb2..ba24369 100644
--- a/core/res/res/drawable-hdpi/ic_popup_sync_6.png
+++ b/core/res/res/drawable-hdpi/ic_popup_sync_6.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_search.png b/core/res/res/drawable-hdpi/ic_search.png
index bf8bd66..6fca0fd 100644
--- a/core/res/res/drawable-hdpi/ic_search.png
+++ b/core/res/res/drawable-hdpi/ic_search.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_search_api_holo_dark.png b/core/res/res/drawable-hdpi/ic_search_api_holo_dark.png
index 8d529b8..ca74dcb 100644
--- a/core/res/res/drawable-hdpi/ic_search_api_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_search_api_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_search_api_holo_light.png b/core/res/res/drawable-hdpi/ic_search_api_holo_light.png
index 8b15ecb..62f7eba 100644
--- a/core/res/res/drawable-hdpi/ic_search_api_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_search_api_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_search_category_default.png b/core/res/res/drawable-hdpi/ic_search_category_default.png
index f78234e..5e09a07 100644
--- a/core/res/res/drawable-hdpi/ic_search_category_default.png
+++ b/core/res/res/drawable-hdpi/ic_search_category_default.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_secure.png b/core/res/res/drawable-hdpi/ic_secure.png
index 5fb62c2..39c93a4 100644
--- a/core/res/res/drawable-hdpi/ic_secure.png
+++ b/core/res/res/drawable-hdpi/ic_secure.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_settings.png b/core/res/res/drawable-hdpi/ic_settings.png
index cfa539f..feb16c8 100644
--- a/core/res/res/drawable-hdpi/ic_settings.png
+++ b/core/res/res/drawable-hdpi/ic_settings.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_settings_language.png b/core/res/res/drawable-hdpi/ic_settings_language.png
index f635b2e..bcd701f 100644
--- a/core/res/res/drawable-hdpi/ic_settings_language.png
+++ b/core/res/res/drawable-hdpi/ic_settings_language.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_sim_card_multi_24px_clr.png b/core/res/res/drawable-hdpi/ic_sim_card_multi_24px_clr.png
index c4a66bb..af026d1 100644
--- a/core/res/res/drawable-hdpi/ic_sim_card_multi_24px_clr.png
+++ b/core/res/res/drawable-hdpi/ic_sim_card_multi_24px_clr.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_sim_card_multi_48px_clr.png b/core/res/res/drawable-hdpi/ic_sim_card_multi_48px_clr.png
index db901d9..df9c5ff 100644
--- a/core/res/res/drawable-hdpi/ic_sim_card_multi_48px_clr.png
+++ b/core/res/res/drawable-hdpi/ic_sim_card_multi_48px_clr.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_star_half_black_16dp.png b/core/res/res/drawable-hdpi/ic_star_half_black_16dp.png
index 89919a32..ea6a2c5 100644
--- a/core/res/res/drawable-hdpi/ic_star_half_black_16dp.png
+++ b/core/res/res/drawable-hdpi/ic_star_half_black_16dp.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_star_half_black_36dp.png b/core/res/res/drawable-hdpi/ic_star_half_black_36dp.png
index d28afab..0327a4d 100644
--- a/core/res/res/drawable-hdpi/ic_star_half_black_36dp.png
+++ b/core/res/res/drawable-hdpi/ic_star_half_black_36dp.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_star_half_black_48dp.png b/core/res/res/drawable-hdpi/ic_star_half_black_48dp.png
index befe521..8381c3a 100644
--- a/core/res/res/drawable-hdpi/ic_star_half_black_48dp.png
+++ b/core/res/res/drawable-hdpi/ic_star_half_black_48dp.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_sysbar_quicksettings.png b/core/res/res/drawable-hdpi/ic_sysbar_quicksettings.png
index 47b4ba2..b4fcbcb3 100644
--- a/core/res/res/drawable-hdpi/ic_sysbar_quicksettings.png
+++ b/core/res/res/drawable-hdpi/ic_sysbar_quicksettings.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_vibrate.png b/core/res/res/drawable-hdpi/ic_vibrate.png
index ca23372..1d043e1 100644
--- a/core/res/res/drawable-hdpi/ic_vibrate.png
+++ b/core/res/res/drawable-hdpi/ic_vibrate.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_vibrate_small.png b/core/res/res/drawable-hdpi/ic_vibrate_small.png
index 61b8bd9..8d992cc 100644
--- a/core/res/res/drawable-hdpi/ic_vibrate_small.png
+++ b/core/res/res/drawable-hdpi/ic_vibrate_small.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_voice_search.png b/core/res/res/drawable-hdpi/ic_voice_search.png
index 66d14ae..11fdfe0 100644
--- a/core/res/res/drawable-hdpi/ic_voice_search.png
+++ b/core/res/res/drawable-hdpi/ic_voice_search.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_voice_search_api_holo_dark.png b/core/res/res/drawable-hdpi/ic_voice_search_api_holo_dark.png
index 32062a6..be35fb8 100644
--- a/core/res/res/drawable-hdpi/ic_voice_search_api_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_voice_search_api_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_voice_search_api_holo_light.png b/core/res/res/drawable-hdpi/ic_voice_search_api_holo_light.png
index d2b2d21..c33e143 100644
--- a/core/res/res/drawable-hdpi/ic_voice_search_api_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_voice_search_api_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_volume.png b/core/res/res/drawable-hdpi/ic_volume.png
index bf538ee..fe955f1 100644
--- a/core/res/res/drawable-hdpi/ic_volume.png
+++ b/core/res/res/drawable-hdpi/ic_volume.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_volume_bluetooth_ad2p.png b/core/res/res/drawable-hdpi/ic_volume_bluetooth_ad2p.png
index 31851e1..5850a5b 100644
--- a/core/res/res/drawable-hdpi/ic_volume_bluetooth_ad2p.png
+++ b/core/res/res/drawable-hdpi/ic_volume_bluetooth_ad2p.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_volume_bluetooth_in_call.png b/core/res/res/drawable-hdpi/ic_volume_bluetooth_in_call.png
index 108a9e1..20b64d8 100644
--- a/core/res/res/drawable-hdpi/ic_volume_bluetooth_in_call.png
+++ b/core/res/res/drawable-hdpi/ic_volume_bluetooth_in_call.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_volume_off.png b/core/res/res/drawable-hdpi/ic_volume_off.png
index aa344083..70776aa 100644
--- a/core/res/res/drawable-hdpi/ic_volume_off.png
+++ b/core/res/res/drawable-hdpi/ic_volume_off.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_volume_off_small.png b/core/res/res/drawable-hdpi/ic_volume_off_small.png
index 1329414..1899876 100644
--- a/core/res/res/drawable-hdpi/ic_volume_off_small.png
+++ b/core/res/res/drawable-hdpi/ic_volume_off_small.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_volume_small.png b/core/res/res/drawable-hdpi/ic_volume_small.png
index 4e9a7ea..0b5ac9d 100644
--- a/core/res/res/drawable-hdpi/ic_volume_small.png
+++ b/core/res/res/drawable-hdpi/ic_volume_small.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/icon_highlight_rectangle.9.png b/core/res/res/drawable-hdpi/icon_highlight_rectangle.9.png
index a4da974..1d878d83 100644
--- a/core/res/res/drawable-hdpi/icon_highlight_rectangle.9.png
+++ b/core/res/res/drawable-hdpi/icon_highlight_rectangle.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/icon_highlight_square.9.png b/core/res/res/drawable-hdpi/icon_highlight_square.9.png
index 6f9a442..bcea150 100644
--- a/core/res/res/drawable-hdpi/icon_highlight_square.9.png
+++ b/core/res/res/drawable-hdpi/icon_highlight_square.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ime_qwerty.png b/core/res/res/drawable-hdpi/ime_qwerty.png
index f9967cc..bd68b15 100644
--- a/core/res/res/drawable-hdpi/ime_qwerty.png
+++ b/core/res/res/drawable-hdpi/ime_qwerty.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/indicator_input_error.png b/core/res/res/drawable-hdpi/indicator_input_error.png
index 8785376..8373e70 100644
--- a/core/res/res/drawable-hdpi/indicator_input_error.png
+++ b/core/res/res/drawable-hdpi/indicator_input_error.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_dial_arrow_long_left_green.png b/core/res/res/drawable-hdpi/jog_dial_arrow_long_left_green.png
index f19811e..68ceb2d 100644
--- a/core/res/res/drawable-hdpi/jog_dial_arrow_long_left_green.png
+++ b/core/res/res/drawable-hdpi/jog_dial_arrow_long_left_green.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_dial_arrow_long_left_yellow.png b/core/res/res/drawable-hdpi/jog_dial_arrow_long_left_yellow.png
index 0596035..fad3102e 100644
--- a/core/res/res/drawable-hdpi/jog_dial_arrow_long_left_yellow.png
+++ b/core/res/res/drawable-hdpi/jog_dial_arrow_long_left_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_dial_arrow_long_middle_yellow.png b/core/res/res/drawable-hdpi/jog_dial_arrow_long_middle_yellow.png
index 3ab2723..aa4726a 100644
--- a/core/res/res/drawable-hdpi/jog_dial_arrow_long_middle_yellow.png
+++ b/core/res/res/drawable-hdpi/jog_dial_arrow_long_middle_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_dial_arrow_long_right_red.png b/core/res/res/drawable-hdpi/jog_dial_arrow_long_right_red.png
index dd6899f..613d0dd 100644
--- a/core/res/res/drawable-hdpi/jog_dial_arrow_long_right_red.png
+++ b/core/res/res/drawable-hdpi/jog_dial_arrow_long_right_red.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_dial_arrow_long_right_yellow.png b/core/res/res/drawable-hdpi/jog_dial_arrow_long_right_yellow.png
index 27151e0..b10c9e6 100644
--- a/core/res/res/drawable-hdpi/jog_dial_arrow_long_right_yellow.png
+++ b/core/res/res/drawable-hdpi/jog_dial_arrow_long_right_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_dial_arrow_short_left.png b/core/res/res/drawable-hdpi/jog_dial_arrow_short_left.png
index 66d49bb..07a7b5f 100644
--- a/core/res/res/drawable-hdpi/jog_dial_arrow_short_left.png
+++ b/core/res/res/drawable-hdpi/jog_dial_arrow_short_left.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_dial_arrow_short_left_and_right.png b/core/res/res/drawable-hdpi/jog_dial_arrow_short_left_and_right.png
index c47e176..7be1f8a7 100644
--- a/core/res/res/drawable-hdpi/jog_dial_arrow_short_left_and_right.png
+++ b/core/res/res/drawable-hdpi/jog_dial_arrow_short_left_and_right.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_dial_arrow_short_right.png b/core/res/res/drawable-hdpi/jog_dial_arrow_short_right.png
index f5ea157..bba9e6c 100644
--- a/core/res/res/drawable-hdpi/jog_dial_arrow_short_right.png
+++ b/core/res/res/drawable-hdpi/jog_dial_arrow_short_right.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_dial_bg.png b/core/res/res/drawable-hdpi/jog_dial_bg.png
index 8adbfd8..89223a5 100644
--- a/core/res/res/drawable-hdpi/jog_dial_bg.png
+++ b/core/res/res/drawable-hdpi/jog_dial_bg.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_dial_dimple.png b/core/res/res/drawable-hdpi/jog_dial_dimple.png
index 0eaea91..034b985 100644
--- a/core/res/res/drawable-hdpi/jog_dial_dimple.png
+++ b/core/res/res/drawable-hdpi/jog_dial_dimple.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_dial_dimple_dim.png b/core/res/res/drawable-hdpi/jog_dial_dimple_dim.png
index 49effe5..71f12a6 100644
--- a/core/res/res/drawable-hdpi/jog_dial_dimple_dim.png
+++ b/core/res/res/drawable-hdpi/jog_dial_dimple_dim.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_bar_left_end_confirm_gray.9.png b/core/res/res/drawable-hdpi/jog_tab_bar_left_end_confirm_gray.9.png
index abb91cc..ddf44d7 100644
--- a/core/res/res/drawable-hdpi/jog_tab_bar_left_end_confirm_gray.9.png
+++ b/core/res/res/drawable-hdpi/jog_tab_bar_left_end_confirm_gray.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_bar_left_end_confirm_green.9.png b/core/res/res/drawable-hdpi/jog_tab_bar_left_end_confirm_green.9.png
index 7c4f40e..4ba35c6 100644
--- a/core/res/res/drawable-hdpi/jog_tab_bar_left_end_confirm_green.9.png
+++ b/core/res/res/drawable-hdpi/jog_tab_bar_left_end_confirm_green.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_bar_left_end_confirm_red.9.png b/core/res/res/drawable-hdpi/jog_tab_bar_left_end_confirm_red.9.png
index 6dbf925..77f0b83 100644
--- a/core/res/res/drawable-hdpi/jog_tab_bar_left_end_confirm_red.9.png
+++ b/core/res/res/drawable-hdpi/jog_tab_bar_left_end_confirm_red.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_bar_left_end_confirm_yellow.9.png b/core/res/res/drawable-hdpi/jog_tab_bar_left_end_confirm_yellow.9.png
index b05a49f..e53516c 100644
--- a/core/res/res/drawable-hdpi/jog_tab_bar_left_end_confirm_yellow.9.png
+++ b/core/res/res/drawable-hdpi/jog_tab_bar_left_end_confirm_yellow.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_bar_left_end_normal.9.png b/core/res/res/drawable-hdpi/jog_tab_bar_left_end_normal.9.png
index b9ec237..3289735 100644
--- a/core/res/res/drawable-hdpi/jog_tab_bar_left_end_normal.9.png
+++ b/core/res/res/drawable-hdpi/jog_tab_bar_left_end_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_bar_left_end_pressed.9.png b/core/res/res/drawable-hdpi/jog_tab_bar_left_end_pressed.9.png
index 2800cab..864f054 100644
--- a/core/res/res/drawable-hdpi/jog_tab_bar_left_end_pressed.9.png
+++ b/core/res/res/drawable-hdpi/jog_tab_bar_left_end_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_bar_right_end_confirm_gray.9.png b/core/res/res/drawable-hdpi/jog_tab_bar_right_end_confirm_gray.9.png
index 51cbfa6..c23f792 100644
--- a/core/res/res/drawable-hdpi/jog_tab_bar_right_end_confirm_gray.9.png
+++ b/core/res/res/drawable-hdpi/jog_tab_bar_right_end_confirm_gray.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_bar_right_end_confirm_green.9.png b/core/res/res/drawable-hdpi/jog_tab_bar_right_end_confirm_green.9.png
index ca51ccc..a650b47 100644
--- a/core/res/res/drawable-hdpi/jog_tab_bar_right_end_confirm_green.9.png
+++ b/core/res/res/drawable-hdpi/jog_tab_bar_right_end_confirm_green.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_bar_right_end_confirm_red.9.png b/core/res/res/drawable-hdpi/jog_tab_bar_right_end_confirm_red.9.png
index fd98571..26ab64d 100644
--- a/core/res/res/drawable-hdpi/jog_tab_bar_right_end_confirm_red.9.png
+++ b/core/res/res/drawable-hdpi/jog_tab_bar_right_end_confirm_red.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_bar_right_end_confirm_yellow.9.png b/core/res/res/drawable-hdpi/jog_tab_bar_right_end_confirm_yellow.9.png
index 723815b..4592583 100644
--- a/core/res/res/drawable-hdpi/jog_tab_bar_right_end_confirm_yellow.9.png
+++ b/core/res/res/drawable-hdpi/jog_tab_bar_right_end_confirm_yellow.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_bar_right_end_normal.9.png b/core/res/res/drawable-hdpi/jog_tab_bar_right_end_normal.9.png
index 30fcda5..a423ef8d 100644
--- a/core/res/res/drawable-hdpi/jog_tab_bar_right_end_normal.9.png
+++ b/core/res/res/drawable-hdpi/jog_tab_bar_right_end_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_bar_right_end_pressed.9.png b/core/res/res/drawable-hdpi/jog_tab_bar_right_end_pressed.9.png
index ffc5433..6640a0d 100644
--- a/core/res/res/drawable-hdpi/jog_tab_bar_right_end_pressed.9.png
+++ b/core/res/res/drawable-hdpi/jog_tab_bar_right_end_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_left_confirm_gray.png b/core/res/res/drawable-hdpi/jog_tab_left_confirm_gray.png
index 9599fb5..2d118a7 100644
--- a/core/res/res/drawable-hdpi/jog_tab_left_confirm_gray.png
+++ b/core/res/res/drawable-hdpi/jog_tab_left_confirm_gray.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_left_confirm_green.png b/core/res/res/drawable-hdpi/jog_tab_left_confirm_green.png
index 46d9ab3..65c765c3b 100644
--- a/core/res/res/drawable-hdpi/jog_tab_left_confirm_green.png
+++ b/core/res/res/drawable-hdpi/jog_tab_left_confirm_green.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_left_confirm_red.png b/core/res/res/drawable-hdpi/jog_tab_left_confirm_red.png
index 6c0dc0a..1de9b45 100644
--- a/core/res/res/drawable-hdpi/jog_tab_left_confirm_red.png
+++ b/core/res/res/drawable-hdpi/jog_tab_left_confirm_red.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_left_confirm_yellow.png b/core/res/res/drawable-hdpi/jog_tab_left_confirm_yellow.png
index 3f9fb8f..91beabc 100644
--- a/core/res/res/drawable-hdpi/jog_tab_left_confirm_yellow.png
+++ b/core/res/res/drawable-hdpi/jog_tab_left_confirm_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_left_normal.png b/core/res/res/drawable-hdpi/jog_tab_left_normal.png
index d43c5e2..1e89006 100644
--- a/core/res/res/drawable-hdpi/jog_tab_left_normal.png
+++ b/core/res/res/drawable-hdpi/jog_tab_left_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_left_pressed.png b/core/res/res/drawable-hdpi/jog_tab_left_pressed.png
index ec98790..1c12827 100644
--- a/core/res/res/drawable-hdpi/jog_tab_left_pressed.png
+++ b/core/res/res/drawable-hdpi/jog_tab_left_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_right_confirm_gray.png b/core/res/res/drawable-hdpi/jog_tab_right_confirm_gray.png
index 2861e8d..7a5bed0 100644
--- a/core/res/res/drawable-hdpi/jog_tab_right_confirm_gray.png
+++ b/core/res/res/drawable-hdpi/jog_tab_right_confirm_gray.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_right_confirm_green.png b/core/res/res/drawable-hdpi/jog_tab_right_confirm_green.png
index e974bbc..71cb158 100644
--- a/core/res/res/drawable-hdpi/jog_tab_right_confirm_green.png
+++ b/core/res/res/drawable-hdpi/jog_tab_right_confirm_green.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_right_confirm_red.png b/core/res/res/drawable-hdpi/jog_tab_right_confirm_red.png
index 9647fa6..222729d 100644
--- a/core/res/res/drawable-hdpi/jog_tab_right_confirm_red.png
+++ b/core/res/res/drawable-hdpi/jog_tab_right_confirm_red.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_right_confirm_yellow.png b/core/res/res/drawable-hdpi/jog_tab_right_confirm_yellow.png
index ad878e1..41937d9 100644
--- a/core/res/res/drawable-hdpi/jog_tab_right_confirm_yellow.png
+++ b/core/res/res/drawable-hdpi/jog_tab_right_confirm_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_right_normal.png b/core/res/res/drawable-hdpi/jog_tab_right_normal.png
index 1eb4234..07d0958 100644
--- a/core/res/res/drawable-hdpi/jog_tab_right_normal.png
+++ b/core/res/res/drawable-hdpi/jog_tab_right_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_right_pressed.png b/core/res/res/drawable-hdpi/jog_tab_right_pressed.png
index 647e802..63c6f84 100644
--- a/core/res/res/drawable-hdpi/jog_tab_right_pressed.png
+++ b/core/res/res/drawable-hdpi/jog_tab_right_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_target_gray.png b/core/res/res/drawable-hdpi/jog_tab_target_gray.png
index e7ef129..21fdb04 100644
--- a/core/res/res/drawable-hdpi/jog_tab_target_gray.png
+++ b/core/res/res/drawable-hdpi/jog_tab_target_gray.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_target_green.png b/core/res/res/drawable-hdpi/jog_tab_target_green.png
index 17f6b10..b1093b9 100644
--- a/core/res/res/drawable-hdpi/jog_tab_target_green.png
+++ b/core/res/res/drawable-hdpi/jog_tab_target_green.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_target_red.png b/core/res/res/drawable-hdpi/jog_tab_target_red.png
index 8db20bb..5e7e412f 100644
--- a/core/res/res/drawable-hdpi/jog_tab_target_red.png
+++ b/core/res/res/drawable-hdpi/jog_tab_target_red.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_target_yellow.png b/core/res/res/drawable-hdpi/jog_tab_target_yellow.png
index 15045b0..9a91b86 100644
--- a/core/res/res/drawable-hdpi/jog_tab_target_yellow.png
+++ b/core/res/res/drawable-hdpi/jog_tab_target_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/keyboard_accessory_bg_landscape.9.png b/core/res/res/drawable-hdpi/keyboard_accessory_bg_landscape.9.png
index 5b0f6c5a..dcab62b 100644
--- a/core/res/res/drawable-hdpi/keyboard_accessory_bg_landscape.9.png
+++ b/core/res/res/drawable-hdpi/keyboard_accessory_bg_landscape.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/keyboard_background.9.png b/core/res/res/drawable-hdpi/keyboard_background.9.png
index 7a03b8e..4bdfe48 100644
--- a/core/res/res/drawable-hdpi/keyboard_background.9.png
+++ b/core/res/res/drawable-hdpi/keyboard_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/keyboard_key_feedback_background.9.png b/core/res/res/drawable-hdpi/keyboard_key_feedback_background.9.png
index 6ba42db..bb3e422 100644
--- a/core/res/res/drawable-hdpi/keyboard_key_feedback_background.9.png
+++ b/core/res/res/drawable-hdpi/keyboard_key_feedback_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/keyboard_key_feedback_more_background.9.png b/core/res/res/drawable-hdpi/keyboard_key_feedback_more_background.9.png
index 4d0b6010..60c6521 100644
--- a/core/res/res/drawable-hdpi/keyboard_key_feedback_more_background.9.png
+++ b/core/res/res/drawable-hdpi/keyboard_key_feedback_more_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/keyboard_popup_panel_background.9.png b/core/res/res/drawable-hdpi/keyboard_popup_panel_background.9.png
index 8e2461b..28a273f 100644
--- a/core/res/res/drawable-hdpi/keyboard_popup_panel_background.9.png
+++ b/core/res/res/drawable-hdpi/keyboard_popup_panel_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/keyboard_popup_panel_trans_background.9.png b/core/res/res/drawable-hdpi/keyboard_popup_panel_trans_background.9.png
index fd7366e..4f75e94 100644
--- a/core/res/res/drawable-hdpi/keyboard_popup_panel_trans_background.9.png
+++ b/core/res/res/drawable-hdpi/keyboard_popup_panel_trans_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/light_header.9.png b/core/res/res/drawable-hdpi/light_header.9.png
index 6fc53ca..7ee8924 100644
--- a/core/res/res/drawable-hdpi/light_header.9.png
+++ b/core/res/res/drawable-hdpi/light_header.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_activated_holo.9.png b/core/res/res/drawable-hdpi/list_activated_holo.9.png
index 4ea7afa..464e0ac 100644
--- a/core/res/res/drawable-hdpi/list_activated_holo.9.png
+++ b/core/res/res/drawable-hdpi/list_activated_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_divider_holo_dark.9.png b/core/res/res/drawable-hdpi/list_divider_holo_dark.9.png
index 986ab0b..b78f409 100644
--- a/core/res/res/drawable-hdpi/list_divider_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/list_divider_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_divider_holo_light.9.png b/core/res/res/drawable-hdpi/list_divider_holo_light.9.png
index 0279e17..ab53898 100644
--- a/core/res/res/drawable-hdpi/list_divider_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/list_divider_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_divider_horizontal_holo_dark.9.png b/core/res/res/drawable-hdpi/list_divider_horizontal_holo_dark.9.png
index 0a4347f..cb477c2 100644
--- a/core/res/res/drawable-hdpi/list_divider_horizontal_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/list_divider_horizontal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_focused_holo.9.png b/core/res/res/drawable-hdpi/list_focused_holo.9.png
index 5552708..d3bd10b 100644
--- a/core/res/res/drawable-hdpi/list_focused_holo.9.png
+++ b/core/res/res/drawable-hdpi/list_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_longpressed_holo.9.png b/core/res/res/drawable-hdpi/list_longpressed_holo.9.png
index 4ea7afa..464e0ac 100644
--- a/core/res/res/drawable-hdpi/list_longpressed_holo.9.png
+++ b/core/res/res/drawable-hdpi/list_longpressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_longpressed_holo_dark.9.png b/core/res/res/drawable-hdpi/list_longpressed_holo_dark.9.png
index f5cc0ed..03236b3 100644
--- a/core/res/res/drawable-hdpi/list_longpressed_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/list_longpressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_longpressed_holo_light.9.png b/core/res/res/drawable-hdpi/list_longpressed_holo_light.9.png
index e9afcc9..ae6e62b 100644
--- a/core/res/res/drawable-hdpi/list_longpressed_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/list_longpressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/list_pressed_holo_dark.9.png
index 596accb..8f84ffa 100644
--- a/core/res/res/drawable-hdpi/list_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/list_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/list_pressed_holo_light.9.png
index 2054530..5c6c065 100644
--- a/core/res/res/drawable-hdpi/list_pressed_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/list_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_section_divider_holo_dark.9.png b/core/res/res/drawable-hdpi/list_section_divider_holo_dark.9.png
index 43a20ad..72d84ad9 100644
--- a/core/res/res/drawable-hdpi/list_section_divider_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/list_section_divider_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_section_divider_holo_light.9.png b/core/res/res/drawable-hdpi/list_section_divider_holo_light.9.png
index b7b292e..8483712 100644
--- a/core/res/res/drawable-hdpi/list_section_divider_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/list_section_divider_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_section_divider_mtrl_alpha.9.png b/core/res/res/drawable-hdpi/list_section_divider_mtrl_alpha.9.png
index 20baf2a..ef20ac7 100644
--- a/core/res/res/drawable-hdpi/list_section_divider_mtrl_alpha.9.png
+++ b/core/res/res/drawable-hdpi/list_section_divider_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_section_header_holo_dark.9.png b/core/res/res/drawable-hdpi/list_section_header_holo_dark.9.png
index 2030d3b..2a77d86 100644
--- a/core/res/res/drawable-hdpi/list_section_header_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/list_section_header_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_section_header_holo_light.9.png b/core/res/res/drawable-hdpi/list_section_header_holo_light.9.png
index 4ca2773..160cb94d 100644
--- a/core/res/res/drawable-hdpi/list_section_header_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/list_section_header_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selected_holo_dark.9.png b/core/res/res/drawable-hdpi/list_selected_holo_dark.9.png
index 1a0bf0d..90a8229 100644
--- a/core/res/res/drawable-hdpi/list_selected_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/list_selected_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selected_holo_light.9.png b/core/res/res/drawable-hdpi/list_selected_holo_light.9.png
index c9e662d..6a88eda 100644
--- a/core/res/res/drawable-hdpi/list_selected_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/list_selected_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_activated_holo_dark.9.png b/core/res/res/drawable-hdpi/list_selector_activated_holo_dark.9.png
index 1a516c1..df1aedc 100644
--- a/core/res/res/drawable-hdpi/list_selector_activated_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/list_selector_activated_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_activated_holo_light.9.png b/core/res/res/drawable-hdpi/list_selector_activated_holo_light.9.png
index f22217b..2dbbc7b 100644
--- a/core/res/res/drawable-hdpi/list_selector_activated_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/list_selector_activated_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_background_default.9.png b/core/res/res/drawable-hdpi/list_selector_background_default.9.png
index 25c6241..9f57d71 100644
--- a/core/res/res/drawable-hdpi/list_selector_background_default.9.png
+++ b/core/res/res/drawable-hdpi/list_selector_background_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_background_default_light.9.png b/core/res/res/drawable-hdpi/list_selector_background_default_light.9.png
index c3e69f0..119775b 100644
--- a/core/res/res/drawable-hdpi/list_selector_background_default_light.9.png
+++ b/core/res/res/drawable-hdpi/list_selector_background_default_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_background_disabled.9.png b/core/res/res/drawable-hdpi/list_selector_background_disabled.9.png
index 05b1419..bc77dcbc 100644
--- a/core/res/res/drawable-hdpi/list_selector_background_disabled.9.png
+++ b/core/res/res/drawable-hdpi/list_selector_background_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_background_disabled_light.9.png b/core/res/res/drawable-hdpi/list_selector_background_disabled_light.9.png
index 8edc9cd..be99053 100644
--- a/core/res/res/drawable-hdpi/list_selector_background_disabled_light.9.png
+++ b/core/res/res/drawable-hdpi/list_selector_background_disabled_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_background_focus.9.png b/core/res/res/drawable-hdpi/list_selector_background_focus.9.png
index 3a21d35..02cca43 100644
--- a/core/res/res/drawable-hdpi/list_selector_background_focus.9.png
+++ b/core/res/res/drawable-hdpi/list_selector_background_focus.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_background_focused.9.png b/core/res/res/drawable-hdpi/list_selector_background_focused.9.png
index 60bb454..f7ecfea 100644
--- a/core/res/res/drawable-hdpi/list_selector_background_focused.9.png
+++ b/core/res/res/drawable-hdpi/list_selector_background_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_background_focused_light.9.png b/core/res/res/drawable-hdpi/list_selector_background_focused_light.9.png
index 60bb454..f7ecfea 100644
--- a/core/res/res/drawable-hdpi/list_selector_background_focused_light.9.png
+++ b/core/res/res/drawable-hdpi/list_selector_background_focused_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_background_focused_selected.9.png b/core/res/res/drawable-hdpi/list_selector_background_focused_selected.9.png
index b527da15..6d6513f 100644
--- a/core/res/res/drawable-hdpi/list_selector_background_focused_selected.9.png
+++ b/core/res/res/drawable-hdpi/list_selector_background_focused_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_background_longpress.9.png b/core/res/res/drawable-hdpi/list_selector_background_longpress.9.png
index 19558e9..efb1765 100644
--- a/core/res/res/drawable-hdpi/list_selector_background_longpress.9.png
+++ b/core/res/res/drawable-hdpi/list_selector_background_longpress.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_background_longpress_light.9.png b/core/res/res/drawable-hdpi/list_selector_background_longpress_light.9.png
index fc2ba2e..f72e373 100644
--- a/core/res/res/drawable-hdpi/list_selector_background_longpress_light.9.png
+++ b/core/res/res/drawable-hdpi/list_selector_background_longpress_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_background_pressed.9.png b/core/res/res/drawable-hdpi/list_selector_background_pressed.9.png
index 0f3b444..ac63b2e 100644
--- a/core/res/res/drawable-hdpi/list_selector_background_pressed.9.png
+++ b/core/res/res/drawable-hdpi/list_selector_background_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_background_pressed_light.9.png b/core/res/res/drawable-hdpi/list_selector_background_pressed_light.9.png
index 00786e5..5a7ae5a 100644
--- a/core/res/res/drawable-hdpi/list_selector_background_pressed_light.9.png
+++ b/core/res/res/drawable-hdpi/list_selector_background_pressed_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_background_selected.9.png b/core/res/res/drawable-hdpi/list_selector_background_selected.9.png
index cbf50b3..fa94d4b 100644
--- a/core/res/res/drawable-hdpi/list_selector_background_selected.9.png
+++ b/core/res/res/drawable-hdpi/list_selector_background_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_background_selected_light.9.png b/core/res/res/drawable-hdpi/list_selector_background_selected_light.9.png
index 34ea86e..5989416 100644
--- a/core/res/res/drawable-hdpi/list_selector_background_selected_light.9.png
+++ b/core/res/res/drawable-hdpi/list_selector_background_selected_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/list_selector_disabled_holo_dark.9.png
index f6fd30d..71d5fe1 100644
--- a/core/res/res/drawable-hdpi/list_selector_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/list_selector_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_disabled_holo_light.9.png b/core/res/res/drawable-hdpi/list_selector_disabled_holo_light.9.png
index ca8e9a2..ca8a43a 100644
--- a/core/res/res/drawable-hdpi/list_selector_disabled_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/list_selector_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/list_selector_focused_holo_dark.9.png
index c1f3d7d..5c5feb8 100644
--- a/core/res/res/drawable-hdpi/list_selector_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/list_selector_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_focused_holo_light.9.png b/core/res/res/drawable-hdpi/list_selector_focused_holo_light.9.png
index 99bb246..9998eb3 100644
--- a/core/res/res/drawable-hdpi/list_selector_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/list_selector_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_multiselect_holo_dark.9.png b/core/res/res/drawable-hdpi/list_selector_multiselect_holo_dark.9.png
index f702fc8..e227c81 100644
--- a/core/res/res/drawable-hdpi/list_selector_multiselect_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/list_selector_multiselect_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_multiselect_holo_light.9.png b/core/res/res/drawable-hdpi/list_selector_multiselect_holo_light.9.png
index e8f277d..f2c0aa1 100644
--- a/core/res/res/drawable-hdpi/list_selector_multiselect_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/list_selector_multiselect_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/list_selector_pressed_holo_dark.9.png
index 0ed5ba3..4cfb714 100644
--- a/core/res/res/drawable-hdpi/list_selector_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/list_selector_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/list_selector_pressed_holo_light.9.png
index 1471c17..88aab73 100644
--- a/core/res/res/drawable-hdpi/list_selector_pressed_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/list_selector_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/magnified_region_frame.9.png b/core/res/res/drawable-hdpi/magnified_region_frame.9.png
index 29bdc42..54d4c26 100644
--- a/core/res/res/drawable-hdpi/magnified_region_frame.9.png
+++ b/core/res/res/drawable-hdpi/magnified_region_frame.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/maps_google_logo.png b/core/res/res/drawable-hdpi/maps_google_logo.png
index 5956ee2..4a46c29 100644
--- a/core/res/res/drawable-hdpi/maps_google_logo.png
+++ b/core/res/res/drawable-hdpi/maps_google_logo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/menu_background.9.png b/core/res/res/drawable-hdpi/menu_background.9.png
index f4c9e08..dcbafe1 100644
--- a/core/res/res/drawable-hdpi/menu_background.9.png
+++ b/core/res/res/drawable-hdpi/menu_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/menu_background_fill_parent_width.9.png b/core/res/res/drawable-hdpi/menu_background_fill_parent_width.9.png
index a3cec11..7dadafa 100644
--- a/core/res/res/drawable-hdpi/menu_background_fill_parent_width.9.png
+++ b/core/res/res/drawable-hdpi/menu_background_fill_parent_width.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_dark.9.png b/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_dark.9.png
index 72ee35f..a431dba 100644
--- a/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_light.9.png b/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_light.9.png
index 0d1f9bf..fe3daca 100644
--- a/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/menu_hardkey_panel_holo_dark.9.png b/core/res/res/drawable-hdpi/menu_hardkey_panel_holo_dark.9.png
index 465ee6d..46bfd33 100644
--- a/core/res/res/drawable-hdpi/menu_hardkey_panel_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/menu_hardkey_panel_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/menu_hardkey_panel_holo_light.9.png b/core/res/res/drawable-hdpi/menu_hardkey_panel_holo_light.9.png
index 76a5c53..b4aaf91 100644
--- a/core/res/res/drawable-hdpi/menu_hardkey_panel_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/menu_hardkey_panel_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/menu_popup_panel_holo_dark.9.png b/core/res/res/drawable-hdpi/menu_popup_panel_holo_dark.9.png
index e5ff886..e3efcf0 100644
--- a/core/res/res/drawable-hdpi/menu_popup_panel_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/menu_popup_panel_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/menu_popup_panel_holo_light.9.png b/core/res/res/drawable-hdpi/menu_popup_panel_holo_light.9.png
index 06d1653..739740f 100644
--- a/core/res/res/drawable-hdpi/menu_popup_panel_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/menu_popup_panel_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/menu_separator.9.png b/core/res/res/drawable-hdpi/menu_separator.9.png
index 3685b4e..29e360b 100644
--- a/core/res/res/drawable-hdpi/menu_separator.9.png
+++ b/core/res/res/drawable-hdpi/menu_separator.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/menu_submenu_background.9.png b/core/res/res/drawable-hdpi/menu_submenu_background.9.png
index 7b7c8b2..7b7a312 100644
--- a/core/res/res/drawable-hdpi/menu_submenu_background.9.png
+++ b/core/res/res/drawable-hdpi/menu_submenu_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/menuitem_background_focus.9.png b/core/res/res/drawable-hdpi/menuitem_background_focus.9.png
index d8e16b99..c5c9766 100644
--- a/core/res/res/drawable-hdpi/menuitem_background_focus.9.png
+++ b/core/res/res/drawable-hdpi/menuitem_background_focus.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/menuitem_background_pressed.9.png b/core/res/res/drawable-hdpi/menuitem_background_pressed.9.png
index ba79cf7..fe5943f 100644
--- a/core/res/res/drawable-hdpi/menuitem_background_pressed.9.png
+++ b/core/res/res/drawable-hdpi/menuitem_background_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/menuitem_background_solid_focused.9.png b/core/res/res/drawable-hdpi/menuitem_background_solid_focused.9.png
index 99dd9b1..533bda8 100644
--- a/core/res/res/drawable-hdpi/menuitem_background_solid_focused.9.png
+++ b/core/res/res/drawable-hdpi/menuitem_background_solid_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/menuitem_background_solid_pressed.9.png b/core/res/res/drawable-hdpi/menuitem_background_solid_pressed.9.png
index 389063a..233e108 100644
--- a/core/res/res/drawable-hdpi/menuitem_background_solid_pressed.9.png
+++ b/core/res/res/drawable-hdpi/menuitem_background_solid_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/menuitem_checkbox_on.png b/core/res/res/drawable-hdpi/menuitem_checkbox_on.png
index e90f631..4f317da 100644
--- a/core/res/res/drawable-hdpi/menuitem_checkbox_on.png
+++ b/core/res/res/drawable-hdpi/menuitem_checkbox_on.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/minitab_lt_focus.9.png b/core/res/res/drawable-hdpi/minitab_lt_focus.9.png
index 3ba8376..88f7b4d9 100644
--- a/core/res/res/drawable-hdpi/minitab_lt_focus.9.png
+++ b/core/res/res/drawable-hdpi/minitab_lt_focus.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/minitab_lt_press.9.png b/core/res/res/drawable-hdpi/minitab_lt_press.9.png
index df226c7..4ff9ede 100644
--- a/core/res/res/drawable-hdpi/minitab_lt_press.9.png
+++ b/core/res/res/drawable-hdpi/minitab_lt_press.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/minitab_lt_selected.9.png b/core/res/res/drawable-hdpi/minitab_lt_selected.9.png
index bb417e6..0383487 100644
--- a/core/res/res/drawable-hdpi/minitab_lt_selected.9.png
+++ b/core/res/res/drawable-hdpi/minitab_lt_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/minitab_lt_unselected.9.png b/core/res/res/drawable-hdpi/minitab_lt_unselected.9.png
index d9ef49e..5a8ff21 100644
--- a/core/res/res/drawable-hdpi/minitab_lt_unselected.9.png
+++ b/core/res/res/drawable-hdpi/minitab_lt_unselected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/minitab_lt_unselected_press.9.png b/core/res/res/drawable-hdpi/minitab_lt_unselected_press.9.png
index 383c4fc..e76724a 100644
--- a/core/res/res/drawable-hdpi/minitab_lt_unselected_press.9.png
+++ b/core/res/res/drawable-hdpi/minitab_lt_unselected_press.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_down_disabled.9.png b/core/res/res/drawable-hdpi/numberpicker_down_disabled.9.png
index 73b6915..e2a3d43 100644
--- a/core/res/res/drawable-hdpi/numberpicker_down_disabled.9.png
+++ b/core/res/res/drawable-hdpi/numberpicker_down_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_down_disabled_focused.9.png b/core/res/res/drawable-hdpi/numberpicker_down_disabled_focused.9.png
index 046e60f..c9856968 100644
--- a/core/res/res/drawable-hdpi/numberpicker_down_disabled_focused.9.png
+++ b/core/res/res/drawable-hdpi/numberpicker_down_disabled_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_down_normal.9.png b/core/res/res/drawable-hdpi/numberpicker_down_normal.9.png
index 9baf7cc..91f1013 100644
--- a/core/res/res/drawable-hdpi/numberpicker_down_normal.9.png
+++ b/core/res/res/drawable-hdpi/numberpicker_down_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_down_pressed.9.png b/core/res/res/drawable-hdpi/numberpicker_down_pressed.9.png
index d95fdd3..82626b5 100644
--- a/core/res/res/drawable-hdpi/numberpicker_down_pressed.9.png
+++ b/core/res/res/drawable-hdpi/numberpicker_down_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_down_selected.9.png b/core/res/res/drawable-hdpi/numberpicker_down_selected.9.png
index a84448f..b695d5a 100644
--- a/core/res/res/drawable-hdpi/numberpicker_down_selected.9.png
+++ b/core/res/res/drawable-hdpi/numberpicker_down_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_input_disabled.9.png b/core/res/res/drawable-hdpi/numberpicker_input_disabled.9.png
index aa17a98..9a4f2f0 100644
--- a/core/res/res/drawable-hdpi/numberpicker_input_disabled.9.png
+++ b/core/res/res/drawable-hdpi/numberpicker_input_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_input_normal.9.png b/core/res/res/drawable-hdpi/numberpicker_input_normal.9.png
index be78a58..8ec4443 100644
--- a/core/res/res/drawable-hdpi/numberpicker_input_normal.9.png
+++ b/core/res/res/drawable-hdpi/numberpicker_input_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_input_pressed.9.png b/core/res/res/drawable-hdpi/numberpicker_input_pressed.9.png
index b28f66c..0966325 100644
--- a/core/res/res/drawable-hdpi/numberpicker_input_pressed.9.png
+++ b/core/res/res/drawable-hdpi/numberpicker_input_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_input_selected.9.png b/core/res/res/drawable-hdpi/numberpicker_input_selected.9.png
index 2e175e8..fd90b7e 100644
--- a/core/res/res/drawable-hdpi/numberpicker_input_selected.9.png
+++ b/core/res/res/drawable-hdpi/numberpicker_input_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_selection_divider.9.png b/core/res/res/drawable-hdpi/numberpicker_selection_divider.9.png
index c9c72ba..907ffee 100644
--- a/core/res/res/drawable-hdpi/numberpicker_selection_divider.9.png
+++ b/core/res/res/drawable-hdpi/numberpicker_selection_divider.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_up_disabled.9.png b/core/res/res/drawable-hdpi/numberpicker_up_disabled.9.png
index 348e48c..8775da5 100644
--- a/core/res/res/drawable-hdpi/numberpicker_up_disabled.9.png
+++ b/core/res/res/drawable-hdpi/numberpicker_up_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_up_disabled_focused.9.png b/core/res/res/drawable-hdpi/numberpicker_up_disabled_focused.9.png
index 93cf3a0..910ebaa 100644
--- a/core/res/res/drawable-hdpi/numberpicker_up_disabled_focused.9.png
+++ b/core/res/res/drawable-hdpi/numberpicker_up_disabled_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_up_normal.9.png b/core/res/res/drawable-hdpi/numberpicker_up_normal.9.png
index b4acced..c844913 100644
--- a/core/res/res/drawable-hdpi/numberpicker_up_normal.9.png
+++ b/core/res/res/drawable-hdpi/numberpicker_up_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_up_pressed.9.png b/core/res/res/drawable-hdpi/numberpicker_up_pressed.9.png
index bd29510..97fe7e1 100644
--- a/core/res/res/drawable-hdpi/numberpicker_up_pressed.9.png
+++ b/core/res/res/drawable-hdpi/numberpicker_up_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_up_selected.9.png b/core/res/res/drawable-hdpi/numberpicker_up_selected.9.png
index a666998..c3987df 100644
--- a/core/res/res/drawable-hdpi/numberpicker_up_selected.9.png
+++ b/core/res/res/drawable-hdpi/numberpicker_up_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/panel_background.9.png b/core/res/res/drawable-hdpi/panel_background.9.png
index 03175d4..e5d103e 100644
--- a/core/res/res/drawable-hdpi/panel_background.9.png
+++ b/core/res/res/drawable-hdpi/panel_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/panel_bg_holo_dark.9.png b/core/res/res/drawable-hdpi/panel_bg_holo_dark.9.png
index a5ac279..ba8f16e 100644
--- a/core/res/res/drawable-hdpi/panel_bg_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/panel_bg_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/panel_bg_holo_light.9.png b/core/res/res/drawable-hdpi/panel_bg_holo_light.9.png
index 583865e..23a7a21 100644
--- a/core/res/res/drawable-hdpi/panel_bg_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/panel_bg_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/panel_picture_frame_bg_focus_blue.9.png b/core/res/res/drawable-hdpi/panel_picture_frame_bg_focus_blue.9.png
index fdafdf5..b485027 100644
--- a/core/res/res/drawable-hdpi/panel_picture_frame_bg_focus_blue.9.png
+++ b/core/res/res/drawable-hdpi/panel_picture_frame_bg_focus_blue.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/panel_picture_frame_bg_normal.9.png b/core/res/res/drawable-hdpi/panel_picture_frame_bg_normal.9.png
index a654277..a85215b 100644
--- a/core/res/res/drawable-hdpi/panel_picture_frame_bg_normal.9.png
+++ b/core/res/res/drawable-hdpi/panel_picture_frame_bg_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/panel_picture_frame_bg_pressed_blue.9.png b/core/res/res/drawable-hdpi/panel_picture_frame_bg_pressed_blue.9.png
index 73162a5..1992db2 100644
--- a/core/res/res/drawable-hdpi/panel_picture_frame_bg_pressed_blue.9.png
+++ b/core/res/res/drawable-hdpi/panel_picture_frame_bg_pressed_blue.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/password_field_default.9.png b/core/res/res/drawable-hdpi/password_field_default.9.png
index 2c424f0..535601f 100644
--- a/core/res/res/drawable-hdpi/password_field_default.9.png
+++ b/core/res/res/drawable-hdpi/password_field_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/password_keyboard_background_holo.9.png b/core/res/res/drawable-hdpi/password_keyboard_background_holo.9.png
index c56c704..1cdbfb3 100644
--- a/core/res/res/drawable-hdpi/password_keyboard_background_holo.9.png
+++ b/core/res/res/drawable-hdpi/password_keyboard_background_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_accessibility_features.png b/core/res/res/drawable-hdpi/perm_group_accessibility_features.png
index c2b5960..121abe4 100644
--- a/core/res/res/drawable-hdpi/perm_group_accessibility_features.png
+++ b/core/res/res/drawable-hdpi/perm_group_accessibility_features.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_affects_battery.png b/core/res/res/drawable-hdpi/perm_group_affects_battery.png
index 945b4686..5bb61a2 100644
--- a/core/res/res/drawable-hdpi/perm_group_affects_battery.png
+++ b/core/res/res/drawable-hdpi/perm_group_affects_battery.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_app_info.png b/core/res/res/drawable-hdpi/perm_group_app_info.png
index 754529e..a35689b 100644
--- a/core/res/res/drawable-hdpi/perm_group_app_info.png
+++ b/core/res/res/drawable-hdpi/perm_group_app_info.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_audio_settings.png b/core/res/res/drawable-hdpi/perm_group_audio_settings.png
index 7e5808a..61a404b 100644
--- a/core/res/res/drawable-hdpi/perm_group_audio_settings.png
+++ b/core/res/res/drawable-hdpi/perm_group_audio_settings.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_bluetooth.png b/core/res/res/drawable-hdpi/perm_group_bluetooth.png
index dac7071..50f0268 100644
--- a/core/res/res/drawable-hdpi/perm_group_bluetooth.png
+++ b/core/res/res/drawable-hdpi/perm_group_bluetooth.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_bookmarks.png b/core/res/res/drawable-hdpi/perm_group_bookmarks.png
index 0cb0c1d..1a070d1 100644
--- a/core/res/res/drawable-hdpi/perm_group_bookmarks.png
+++ b/core/res/res/drawable-hdpi/perm_group_bookmarks.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_device_alarms.png b/core/res/res/drawable-hdpi/perm_group_device_alarms.png
index f38c5fe..db4019d 100644
--- a/core/res/res/drawable-hdpi/perm_group_device_alarms.png
+++ b/core/res/res/drawable-hdpi/perm_group_device_alarms.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_display.png b/core/res/res/drawable-hdpi/perm_group_display.png
index c10c5d8..b90c305 100644
--- a/core/res/res/drawable-hdpi/perm_group_display.png
+++ b/core/res/res/drawable-hdpi/perm_group_display.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_network.png b/core/res/res/drawable-hdpi/perm_group_network.png
index 0ecb7b2..f10a24b 100644
--- a/core/res/res/drawable-hdpi/perm_group_network.png
+++ b/core/res/res/drawable-hdpi/perm_group_network.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_personal_info.png b/core/res/res/drawable-hdpi/perm_group_personal_info.png
index e1b8a5b..2815a70 100644
--- a/core/res/res/drawable-hdpi/perm_group_personal_info.png
+++ b/core/res/res/drawable-hdpi/perm_group_personal_info.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_screenlock.png b/core/res/res/drawable-hdpi/perm_group_screenlock.png
index b5a19ee..461edf6 100644
--- a/core/res/res/drawable-hdpi/perm_group_screenlock.png
+++ b/core/res/res/drawable-hdpi/perm_group_screenlock.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_shortrange_network.png b/core/res/res/drawable-hdpi/perm_group_shortrange_network.png
index 99ca933..d3a0d6b 100644
--- a/core/res/res/drawable-hdpi/perm_group_shortrange_network.png
+++ b/core/res/res/drawable-hdpi/perm_group_shortrange_network.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_status_bar.png b/core/res/res/drawable-hdpi/perm_group_status_bar.png
index e3f6ed9..859efa6 100644
--- a/core/res/res/drawable-hdpi/perm_group_status_bar.png
+++ b/core/res/res/drawable-hdpi/perm_group_status_bar.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_sync_settings.png b/core/res/res/drawable-hdpi/perm_group_sync_settings.png
index 1ca6b17..1aa0aa7 100644
--- a/core/res/res/drawable-hdpi/perm_group_sync_settings.png
+++ b/core/res/res/drawable-hdpi/perm_group_sync_settings.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_system_clock.png b/core/res/res/drawable-hdpi/perm_group_system_clock.png
index 3dd4682..111c667 100644
--- a/core/res/res/drawable-hdpi/perm_group_system_clock.png
+++ b/core/res/res/drawable-hdpi/perm_group_system_clock.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_system_tools.png b/core/res/res/drawable-hdpi/perm_group_system_tools.png
index ae1ba2a..446230c2 100644
--- a/core/res/res/drawable-hdpi/perm_group_system_tools.png
+++ b/core/res/res/drawable-hdpi/perm_group_system_tools.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_voicemail.png b/core/res/res/drawable-hdpi/perm_group_voicemail.png
index 3b245d6..ee7e1e95 100644
--- a/core/res/res/drawable-hdpi/perm_group_voicemail.png
+++ b/core/res/res/drawable-hdpi/perm_group_voicemail.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_wallpaper.png b/core/res/res/drawable-hdpi/perm_group_wallpaper.png
index e40c4f0..2fce038 100644
--- a/core/res/res/drawable-hdpi/perm_group_wallpaper.png
+++ b/core/res/res/drawable-hdpi/perm_group_wallpaper.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/picture_emergency.png b/core/res/res/drawable-hdpi/picture_emergency.png
index 0e13a43..0787bf1 100644
--- a/core/res/res/drawable-hdpi/picture_emergency.png
+++ b/core/res/res/drawable-hdpi/picture_emergency.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/picture_frame.9.png b/core/res/res/drawable-hdpi/picture_frame.9.png
index c038b2a..36b7903 100644
--- a/core/res/res/drawable-hdpi/picture_frame.9.png
+++ b/core/res/res/drawable-hdpi/picture_frame.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/pointer_arrow.png b/core/res/res/drawable-hdpi/pointer_arrow.png
index 0ff0fce..85d066e 100644
--- a/core/res/res/drawable-hdpi/pointer_arrow.png
+++ b/core/res/res/drawable-hdpi/pointer_arrow.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/pointer_spot_anchor.png b/core/res/res/drawable-hdpi/pointer_spot_anchor.png
index bdb5311..784f613 100644
--- a/core/res/res/drawable-hdpi/pointer_spot_anchor.png
+++ b/core/res/res/drawable-hdpi/pointer_spot_anchor.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/pointer_spot_hover.png b/core/res/res/drawable-hdpi/pointer_spot_hover.png
index e7f2a0c..0e8353c 100644
--- a/core/res/res/drawable-hdpi/pointer_spot_hover.png
+++ b/core/res/res/drawable-hdpi/pointer_spot_hover.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/pointer_spot_touch.png b/core/res/res/drawable-hdpi/pointer_spot_touch.png
index 0326f91..3ad9b10 100644
--- a/core/res/res/drawable-hdpi/pointer_spot_touch.png
+++ b/core/res/res/drawable-hdpi/pointer_spot_touch.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_background_mtrl_mult.9.png b/core/res/res/drawable-hdpi/popup_background_mtrl_mult.9.png
index 385734e..e8678cc 100644
--- a/core/res/res/drawable-hdpi/popup_background_mtrl_mult.9.png
+++ b/core/res/res/drawable-hdpi/popup_background_mtrl_mult.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_bottom_bright.9.png b/core/res/res/drawable-hdpi/popup_bottom_bright.9.png
index 6e5fbb5..d246e568 100644
--- a/core/res/res/drawable-hdpi/popup_bottom_bright.9.png
+++ b/core/res/res/drawable-hdpi/popup_bottom_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_bottom_dark.9.png b/core/res/res/drawable-hdpi/popup_bottom_dark.9.png
index 3434b2d..785c312 100644
--- a/core/res/res/drawable-hdpi/popup_bottom_dark.9.png
+++ b/core/res/res/drawable-hdpi/popup_bottom_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_bottom_medium.9.png b/core/res/res/drawable-hdpi/popup_bottom_medium.9.png
index 673a509..0e9b4f1 100644
--- a/core/res/res/drawable-hdpi/popup_bottom_medium.9.png
+++ b/core/res/res/drawable-hdpi/popup_bottom_medium.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_center_bright.9.png b/core/res/res/drawable-hdpi/popup_center_bright.9.png
index c2a739c..dc91117 100644
--- a/core/res/res/drawable-hdpi/popup_center_bright.9.png
+++ b/core/res/res/drawable-hdpi/popup_center_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_center_dark.9.png b/core/res/res/drawable-hdpi/popup_center_dark.9.png
index 9d2bfb1..9812cbf 100644
--- a/core/res/res/drawable-hdpi/popup_center_dark.9.png
+++ b/core/res/res/drawable-hdpi/popup_center_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_center_medium.9.png b/core/res/res/drawable-hdpi/popup_center_medium.9.png
index 4375bf2d..6a89363 100644
--- a/core/res/res/drawable-hdpi/popup_center_medium.9.png
+++ b/core/res/res/drawable-hdpi/popup_center_medium.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_full_bright.9.png b/core/res/res/drawable-hdpi/popup_full_bright.9.png
index 6b8aa9d..7c69bdf 100644
--- a/core/res/res/drawable-hdpi/popup_full_bright.9.png
+++ b/core/res/res/drawable-hdpi/popup_full_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_full_dark.9.png b/core/res/res/drawable-hdpi/popup_full_dark.9.png
index 2884abe..0cebad0 100644
--- a/core/res/res/drawable-hdpi/popup_full_dark.9.png
+++ b/core/res/res/drawable-hdpi/popup_full_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_inline_error_above_am.9.png b/core/res/res/drawable-hdpi/popup_inline_error_above_am.9.png
index 3d4e8ba..04ab6b5 100644
--- a/core/res/res/drawable-hdpi/popup_inline_error_above_am.9.png
+++ b/core/res/res/drawable-hdpi/popup_inline_error_above_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_inline_error_above_holo_dark_am.9.png b/core/res/res/drawable-hdpi/popup_inline_error_above_holo_dark_am.9.png
index 83b2bce..d347d76 100644
--- a/core/res/res/drawable-hdpi/popup_inline_error_above_holo_dark_am.9.png
+++ b/core/res/res/drawable-hdpi/popup_inline_error_above_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_inline_error_above_holo_light_am.9.png b/core/res/res/drawable-hdpi/popup_inline_error_above_holo_light_am.9.png
index 61ea2b0..92c3eb1 100644
--- a/core/res/res/drawable-hdpi/popup_inline_error_above_holo_light_am.9.png
+++ b/core/res/res/drawable-hdpi/popup_inline_error_above_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_inline_error_am.9.png b/core/res/res/drawable-hdpi/popup_inline_error_am.9.png
index b188d81..3ba4d29 100644
--- a/core/res/res/drawable-hdpi/popup_inline_error_am.9.png
+++ b/core/res/res/drawable-hdpi/popup_inline_error_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_inline_error_holo_dark_am.9.png b/core/res/res/drawable-hdpi/popup_inline_error_holo_dark_am.9.png
index 9f3060d..f990fff 100644
--- a/core/res/res/drawable-hdpi/popup_inline_error_holo_dark_am.9.png
+++ b/core/res/res/drawable-hdpi/popup_inline_error_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_inline_error_holo_light_am.9.png b/core/res/res/drawable-hdpi/popup_inline_error_holo_light_am.9.png
index 84fbdac..a19f966 100644
--- a/core/res/res/drawable-hdpi/popup_inline_error_holo_light_am.9.png
+++ b/core/res/res/drawable-hdpi/popup_inline_error_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_top_bright.9.png b/core/res/res/drawable-hdpi/popup_top_bright.9.png
index 76c35ec..8cbf1b9 100644
--- a/core/res/res/drawable-hdpi/popup_top_bright.9.png
+++ b/core/res/res/drawable-hdpi/popup_top_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_top_dark.9.png b/core/res/res/drawable-hdpi/popup_top_dark.9.png
index f317330..0b81d63 100644
--- a/core/res/res/drawable-hdpi/popup_top_dark.9.png
+++ b/core/res/res/drawable-hdpi/popup_top_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_audio_away.png b/core/res/res/drawable-hdpi/presence_audio_away.png
index c6af4f7..bd2e1dc 100644
--- a/core/res/res/drawable-hdpi/presence_audio_away.png
+++ b/core/res/res/drawable-hdpi/presence_audio_away.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_audio_busy.png b/core/res/res/drawable-hdpi/presence_audio_busy.png
index ddba88d..7a12bf1 100644
--- a/core/res/res/drawable-hdpi/presence_audio_busy.png
+++ b/core/res/res/drawable-hdpi/presence_audio_busy.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_audio_online.png b/core/res/res/drawable-hdpi/presence_audio_online.png
index 058963c..99430ef 100644
--- a/core/res/res/drawable-hdpi/presence_audio_online.png
+++ b/core/res/res/drawable-hdpi/presence_audio_online.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_away.png b/core/res/res/drawable-hdpi/presence_away.png
index c39d3a8..e80d3f5 100644
--- a/core/res/res/drawable-hdpi/presence_away.png
+++ b/core/res/res/drawable-hdpi/presence_away.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_busy.png b/core/res/res/drawable-hdpi/presence_busy.png
index 391d1c9..86dba1c 100644
--- a/core/res/res/drawable-hdpi/presence_busy.png
+++ b/core/res/res/drawable-hdpi/presence_busy.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_invisible.png b/core/res/res/drawable-hdpi/presence_invisible.png
index 8157010..9ce7e4e 100644
--- a/core/res/res/drawable-hdpi/presence_invisible.png
+++ b/core/res/res/drawable-hdpi/presence_invisible.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_offline.png b/core/res/res/drawable-hdpi/presence_offline.png
index dc20b0f..ae62c5a 100644
--- a/core/res/res/drawable-hdpi/presence_offline.png
+++ b/core/res/res/drawable-hdpi/presence_offline.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_online.png b/core/res/res/drawable-hdpi/presence_online.png
index 7694446..e18d3bf 100644
--- a/core/res/res/drawable-hdpi/presence_online.png
+++ b/core/res/res/drawable-hdpi/presence_online.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_video_away.png b/core/res/res/drawable-hdpi/presence_video_away.png
index 0e9e384..176d581 100644
--- a/core/res/res/drawable-hdpi/presence_video_away.png
+++ b/core/res/res/drawable-hdpi/presence_video_away.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_video_busy.png b/core/res/res/drawable-hdpi/presence_video_busy.png
index 5b01840..9401152 100644
--- a/core/res/res/drawable-hdpi/presence_video_busy.png
+++ b/core/res/res/drawable-hdpi/presence_video_busy.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_video_online.png b/core/res/res/drawable-hdpi/presence_video_online.png
index fe285f5..90e652e 100644
--- a/core/res/res/drawable-hdpi/presence_video_online.png
+++ b/core/res/res/drawable-hdpi/presence_video_online.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/pressed_application_background_static.png b/core/res/res/drawable-hdpi/pressed_application_background_static.png
index dae96e6..5a95475 100644
--- a/core/res/res/drawable-hdpi/pressed_application_background_static.png
+++ b/core/res/res/drawable-hdpi/pressed_application_background_static.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progress_bg_holo_dark.9.png b/core/res/res/drawable-hdpi/progress_bg_holo_dark.9.png
index a4c5b8b..0c7510b 100644
--- a/core/res/res/drawable-hdpi/progress_bg_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/progress_bg_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progress_bg_holo_light.9.png b/core/res/res/drawable-hdpi/progress_bg_holo_light.9.png
index 3f12166..b5cd481 100644
--- a/core/res/res/drawable-hdpi/progress_bg_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/progress_bg_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progress_primary_holo_dark.9.png b/core/res/res/drawable-hdpi/progress_primary_holo_dark.9.png
index b73abba..8f7ae3f 100644
--- a/core/res/res/drawable-hdpi/progress_primary_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/progress_primary_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progress_primary_holo_light.9.png b/core/res/res/drawable-hdpi/progress_primary_holo_light.9.png
index 2f76a22..1a1b871 100644
--- a/core/res/res/drawable-hdpi/progress_primary_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/progress_primary_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progress_secondary_holo_dark.9.png b/core/res/res/drawable-hdpi/progress_secondary_holo_dark.9.png
index a75d0dd..2e836d3 100644
--- a/core/res/res/drawable-hdpi/progress_secondary_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/progress_secondary_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progress_secondary_holo_light.9.png b/core/res/res/drawable-hdpi/progress_secondary_holo_light.9.png
index 955b708..2e836d3 100644
--- a/core/res/res/drawable-hdpi/progress_secondary_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/progress_secondary_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progressbar_indeterminate1.png b/core/res/res/drawable-hdpi/progressbar_indeterminate1.png
index 197b34d..397d84b 100644
--- a/core/res/res/drawable-hdpi/progressbar_indeterminate1.png
+++ b/core/res/res/drawable-hdpi/progressbar_indeterminate1.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progressbar_indeterminate2.png b/core/res/res/drawable-hdpi/progressbar_indeterminate2.png
index c6cf008..902369a 100644
--- a/core/res/res/drawable-hdpi/progressbar_indeterminate2.png
+++ b/core/res/res/drawable-hdpi/progressbar_indeterminate2.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progressbar_indeterminate3.png b/core/res/res/drawable-hdpi/progressbar_indeterminate3.png
index bf129e0..d32ff92 100644
--- a/core/res/res/drawable-hdpi/progressbar_indeterminate3.png
+++ b/core/res/res/drawable-hdpi/progressbar_indeterminate3.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo1.png b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo1.png
index 43f9e03..1175a5e 100644
--- a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo1.png
+++ b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo1.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo2.png b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo2.png
index c6d95f3..e2f7bbd 100644
--- a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo2.png
+++ b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo2.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo3.png b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo3.png
index 7829a3c..17b596f 100644
--- a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo3.png
+++ b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo3.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo4.png b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo4.png
index d0842f8..7b4c9da 100644
--- a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo4.png
+++ b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo4.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo5.png b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo5.png
index e78b8f9..94ea84a 100644
--- a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo5.png
+++ b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo5.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo6.png b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo6.png
index 5f9f6c32..ed1a143 100644
--- a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo6.png
+++ b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo6.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo7.png b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo7.png
index d39c4ae..bd010b3 100644
--- a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo7.png
+++ b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo7.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo8.png b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo8.png
index 94a6fae..322b9c1 100644
--- a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo8.png
+++ b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo8.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickactions_arrowdown_left_holo_dark.9.png b/core/res/res/drawable-hdpi/quickactions_arrowdown_left_holo_dark.9.png
index 93a8417..de9a89b 100644
--- a/core/res/res/drawable-hdpi/quickactions_arrowdown_left_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/quickactions_arrowdown_left_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickactions_arrowdown_left_holo_light.9.png b/core/res/res/drawable-hdpi/quickactions_arrowdown_left_holo_light.9.png
index 61e856a..f4cde39 100644
--- a/core/res/res/drawable-hdpi/quickactions_arrowdown_left_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/quickactions_arrowdown_left_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickactions_arrowdown_right_holo_dark.9.png b/core/res/res/drawable-hdpi/quickactions_arrowdown_right_holo_dark.9.png
index 7632a16..1a44145 100644
--- a/core/res/res/drawable-hdpi/quickactions_arrowdown_right_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/quickactions_arrowdown_right_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickactions_arrowdown_right_holo_light.9.png b/core/res/res/drawable-hdpi/quickactions_arrowdown_right_holo_light.9.png
index 8e66ad1..8cb89bc 100644
--- a/core/res/res/drawable-hdpi/quickactions_arrowdown_right_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/quickactions_arrowdown_right_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickactions_arrowup_left_holo_dark.9.png b/core/res/res/drawable-hdpi/quickactions_arrowup_left_holo_dark.9.png
index 02618ca..c275c59 100644
--- a/core/res/res/drawable-hdpi/quickactions_arrowup_left_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/quickactions_arrowup_left_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickactions_arrowup_left_holo_light.9.png b/core/res/res/drawable-hdpi/quickactions_arrowup_left_holo_light.9.png
index 939050d..fceb65c 100644
--- a/core/res/res/drawable-hdpi/quickactions_arrowup_left_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/quickactions_arrowup_left_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickactions_arrowup_left_right_holo_dark.9.png b/core/res/res/drawable-hdpi/quickactions_arrowup_left_right_holo_dark.9.png
index f5cf487..8fe85c7 100644
--- a/core/res/res/drawable-hdpi/quickactions_arrowup_left_right_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/quickactions_arrowup_left_right_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickactions_arrowup_right_holo_light.9.png b/core/res/res/drawable-hdpi/quickactions_arrowup_right_holo_light.9.png
index 1237f26..92ab91c 100644
--- a/core/res/res/drawable-hdpi/quickactions_arrowup_right_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/quickactions_arrowup_right_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_focused_dark_am.9.png b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_focused_dark_am.9.png
index cbd8c5c..4ca14e3 100644
--- a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_focused_dark_am.9.png
+++ b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_focused_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_focused_light_am.9.png b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_focused_light_am.9.png
index f7f4ba3..06e3f97 100644
--- a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_focused_light_am.9.png
+++ b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_focused_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_dark_am.9.png b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_dark_am.9.png
index a82e7ac..dcfa241 100644
--- a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_dark_am.9.png
+++ b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_light_am.9.png b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_light_am.9.png
index db4ce80..5e81836 100644
--- a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_light_am.9.png
+++ b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_dark_am.9.png b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_dark_am.9.png
index 4e40eda..d5124f31 100644
--- a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_dark_am.9.png
+++ b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_light_am.9.png b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_light_am.9.png
index f1b7036..b87c0d6 100644
--- a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_light_am.9.png
+++ b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/radiobutton_off_background.png b/core/res/res/drawable-hdpi/radiobutton_off_background.png
index 5ce33cd..0e8c1f1 100644
--- a/core/res/res/drawable-hdpi/radiobutton_off_background.png
+++ b/core/res/res/drawable-hdpi/radiobutton_off_background.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/radiobutton_on_background.png b/core/res/res/drawable-hdpi/radiobutton_on_background.png
index 0f46071..9398943 100644
--- a/core/res/res/drawable-hdpi/radiobutton_on_background.png
+++ b/core/res/res/drawable-hdpi/radiobutton_on_background.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_big_half.png b/core/res/res/drawable-hdpi/rate_star_big_half.png
index 4a91e87..057d82d 100644
--- a/core/res/res/drawable-hdpi/rate_star_big_half.png
+++ b/core/res/res/drawable-hdpi/rate_star_big_half.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_big_half_holo_dark.png b/core/res/res/drawable-hdpi/rate_star_big_half_holo_dark.png
index 67890f0..9822984 100644
--- a/core/res/res/drawable-hdpi/rate_star_big_half_holo_dark.png
+++ b/core/res/res/drawable-hdpi/rate_star_big_half_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_big_half_holo_light.png b/core/res/res/drawable-hdpi/rate_star_big_half_holo_light.png
index e9ffa5b..d49a1f4 100644
--- a/core/res/res/drawable-hdpi/rate_star_big_half_holo_light.png
+++ b/core/res/res/drawable-hdpi/rate_star_big_half_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_big_off.png b/core/res/res/drawable-hdpi/rate_star_big_off.png
index ae5883e..6cbe551 100644
--- a/core/res/res/drawable-hdpi/rate_star_big_off.png
+++ b/core/res/res/drawable-hdpi/rate_star_big_off.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_big_off_holo_dark.png b/core/res/res/drawable-hdpi/rate_star_big_off_holo_dark.png
index cc08f88..3427df1 100644
--- a/core/res/res/drawable-hdpi/rate_star_big_off_holo_dark.png
+++ b/core/res/res/drawable-hdpi/rate_star_big_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_big_off_holo_light.png b/core/res/res/drawable-hdpi/rate_star_big_off_holo_light.png
index ebdb47b..7317eb7 100644
--- a/core/res/res/drawable-hdpi/rate_star_big_off_holo_light.png
+++ b/core/res/res/drawable-hdpi/rate_star_big_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_big_on.png b/core/res/res/drawable-hdpi/rate_star_big_on.png
index 65c136e..f335832 100644
--- a/core/res/res/drawable-hdpi/rate_star_big_on.png
+++ b/core/res/res/drawable-hdpi/rate_star_big_on.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_big_on_holo_dark.png b/core/res/res/drawable-hdpi/rate_star_big_on_holo_dark.png
index d594c46..55e11ca 100644
--- a/core/res/res/drawable-hdpi/rate_star_big_on_holo_dark.png
+++ b/core/res/res/drawable-hdpi/rate_star_big_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_big_on_holo_light.png b/core/res/res/drawable-hdpi/rate_star_big_on_holo_light.png
index b4fd29b..59e34ee 100644
--- a/core/res/res/drawable-hdpi/rate_star_big_on_holo_light.png
+++ b/core/res/res/drawable-hdpi/rate_star_big_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_med_half.png b/core/res/res/drawable-hdpi/rate_star_med_half.png
index a436980..06ebcde 100644
--- a/core/res/res/drawable-hdpi/rate_star_med_half.png
+++ b/core/res/res/drawable-hdpi/rate_star_med_half.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_med_half_holo_dark.png b/core/res/res/drawable-hdpi/rate_star_med_half_holo_dark.png
index 65f673d..114bdea 100644
--- a/core/res/res/drawable-hdpi/rate_star_med_half_holo_dark.png
+++ b/core/res/res/drawable-hdpi/rate_star_med_half_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_med_half_holo_light.png b/core/res/res/drawable-hdpi/rate_star_med_half_holo_light.png
index d1756c7..d2c2cb9 100644
--- a/core/res/res/drawable-hdpi/rate_star_med_half_holo_light.png
+++ b/core/res/res/drawable-hdpi/rate_star_med_half_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_med_off.png b/core/res/res/drawable-hdpi/rate_star_med_off.png
index 981aabe..e6c3b59 100644
--- a/core/res/res/drawable-hdpi/rate_star_med_off.png
+++ b/core/res/res/drawable-hdpi/rate_star_med_off.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_med_off_holo_dark.png b/core/res/res/drawable-hdpi/rate_star_med_off_holo_dark.png
index b8bca18..884c6e2 100644
--- a/core/res/res/drawable-hdpi/rate_star_med_off_holo_dark.png
+++ b/core/res/res/drawable-hdpi/rate_star_med_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_med_off_holo_light.png b/core/res/res/drawable-hdpi/rate_star_med_off_holo_light.png
index 4605a42..899d5f3 100644
--- a/core/res/res/drawable-hdpi/rate_star_med_off_holo_light.png
+++ b/core/res/res/drawable-hdpi/rate_star_med_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_med_on.png b/core/res/res/drawable-hdpi/rate_star_med_on.png
index 320c14f..f000815 100644
--- a/core/res/res/drawable-hdpi/rate_star_med_on.png
+++ b/core/res/res/drawable-hdpi/rate_star_med_on.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_med_on_holo_dark.png b/core/res/res/drawable-hdpi/rate_star_med_on_holo_dark.png
index 1b7fe77..b1e0f85 100644
--- a/core/res/res/drawable-hdpi/rate_star_med_on_holo_dark.png
+++ b/core/res/res/drawable-hdpi/rate_star_med_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_med_on_holo_light.png b/core/res/res/drawable-hdpi/rate_star_med_on_holo_light.png
index 41f33a8..8054797c 100644
--- a/core/res/res/drawable-hdpi/rate_star_med_on_holo_light.png
+++ b/core/res/res/drawable-hdpi/rate_star_med_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_small_half.png b/core/res/res/drawable-hdpi/rate_star_small_half.png
index 0b8974e1..ce46b33 100644
--- a/core/res/res/drawable-hdpi/rate_star_small_half.png
+++ b/core/res/res/drawable-hdpi/rate_star_small_half.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_small_half_holo_dark.png b/core/res/res/drawable-hdpi/rate_star_small_half_holo_dark.png
index 6cd59ea..66b5960 100644
--- a/core/res/res/drawable-hdpi/rate_star_small_half_holo_dark.png
+++ b/core/res/res/drawable-hdpi/rate_star_small_half_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_small_half_holo_light.png b/core/res/res/drawable-hdpi/rate_star_small_half_holo_light.png
index e03711e..cbb93ca 100644
--- a/core/res/res/drawable-hdpi/rate_star_small_half_holo_light.png
+++ b/core/res/res/drawable-hdpi/rate_star_small_half_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_small_off.png b/core/res/res/drawable-hdpi/rate_star_small_off.png
index 7ae305f..af2b820 100644
--- a/core/res/res/drawable-hdpi/rate_star_small_off.png
+++ b/core/res/res/drawable-hdpi/rate_star_small_off.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_small_off_holo_dark.png b/core/res/res/drawable-hdpi/rate_star_small_off_holo_dark.png
index a5ee171..6685316 100644
--- a/core/res/res/drawable-hdpi/rate_star_small_off_holo_dark.png
+++ b/core/res/res/drawable-hdpi/rate_star_small_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_small_off_holo_light.png b/core/res/res/drawable-hdpi/rate_star_small_off_holo_light.png
index c7fb673..c025258 100644
--- a/core/res/res/drawable-hdpi/rate_star_small_off_holo_light.png
+++ b/core/res/res/drawable-hdpi/rate_star_small_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_small_on.png b/core/res/res/drawable-hdpi/rate_star_small_on.png
index ffa5258..7e87458 100644
--- a/core/res/res/drawable-hdpi/rate_star_small_on.png
+++ b/core/res/res/drawable-hdpi/rate_star_small_on.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_small_on_holo_dark.png b/core/res/res/drawable-hdpi/rate_star_small_on_holo_dark.png
index 134a38b..3aaff42 100644
--- a/core/res/res/drawable-hdpi/rate_star_small_on_holo_dark.png
+++ b/core/res/res/drawable-hdpi/rate_star_small_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_small_on_holo_light.png b/core/res/res/drawable-hdpi/rate_star_small_on_holo_light.png
index 0e7c8a9..7f8dfaa 100644
--- a/core/res/res/drawable-hdpi/rate_star_small_on_holo_light.png
+++ b/core/res/res/drawable-hdpi/rate_star_small_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/recent_dialog_background.9.png b/core/res/res/drawable-hdpi/recent_dialog_background.9.png
index bebcc40..aed361b 100644
--- a/core/res/res/drawable-hdpi/recent_dialog_background.9.png
+++ b/core/res/res/drawable-hdpi/recent_dialog_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/reticle.png b/core/res/res/drawable-hdpi/reticle.png
index a3e8c1b..a37d753 100644
--- a/core/res/res/drawable-hdpi/reticle.png
+++ b/core/res/res/drawable-hdpi/reticle.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrollbar_handle_accelerated_anim2.9.png b/core/res/res/drawable-hdpi/scrollbar_handle_accelerated_anim2.9.png
index fb9e7aa..758215d 100644
--- a/core/res/res/drawable-hdpi/scrollbar_handle_accelerated_anim2.9.png
+++ b/core/res/res/drawable-hdpi/scrollbar_handle_accelerated_anim2.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrollbar_handle_holo_dark.9.png b/core/res/res/drawable-hdpi/scrollbar_handle_holo_dark.9.png
index 3c4a50e..7bbd47c 100644
--- a/core/res/res/drawable-hdpi/scrollbar_handle_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/scrollbar_handle_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrollbar_handle_holo_light.9.png b/core/res/res/drawable-hdpi/scrollbar_handle_holo_light.9.png
index 222c776..c2032db 100644
--- a/core/res/res/drawable-hdpi/scrollbar_handle_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/scrollbar_handle_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrollbar_handle_horizontal.9.png b/core/res/res/drawable-hdpi/scrollbar_handle_horizontal.9.png
index cd206e2..3bd9587 100644
--- a/core/res/res/drawable-hdpi/scrollbar_handle_horizontal.9.png
+++ b/core/res/res/drawable-hdpi/scrollbar_handle_horizontal.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrollbar_handle_vertical.9.png b/core/res/res/drawable-hdpi/scrollbar_handle_vertical.9.png
index 3ec0791..f04e1de 100644
--- a/core/res/res/drawable-hdpi/scrollbar_handle_vertical.9.png
+++ b/core/res/res/drawable-hdpi/scrollbar_handle_vertical.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_control_disabled_holo.png b/core/res/res/drawable-hdpi/scrubber_control_disabled_holo.png
index 370242a..9305a95 100644
--- a/core/res/res/drawable-hdpi/scrubber_control_disabled_holo.png
+++ b/core/res/res/drawable-hdpi/scrubber_control_disabled_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_control_focused_holo.png b/core/res/res/drawable-hdpi/scrubber_control_focused_holo.png
index eea2c3e..cf70693 100644
--- a/core/res/res/drawable-hdpi/scrubber_control_focused_holo.png
+++ b/core/res/res/drawable-hdpi/scrubber_control_focused_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_control_normal_holo.png b/core/res/res/drawable-hdpi/scrubber_control_normal_holo.png
index 3c98ee9..2b4f7ba 100644
--- a/core/res/res/drawable-hdpi/scrubber_control_normal_holo.png
+++ b/core/res/res/drawable-hdpi/scrubber_control_normal_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_control_on_mtrl_alpha.png b/core/res/res/drawable-hdpi/scrubber_control_on_mtrl_alpha.png
index 79de664..c43a6d7 100644
--- a/core/res/res/drawable-hdpi/scrubber_control_on_mtrl_alpha.png
+++ b/core/res/res/drawable-hdpi/scrubber_control_on_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_control_on_pressed_mtrl_alpha.png b/core/res/res/drawable-hdpi/scrubber_control_on_pressed_mtrl_alpha.png
index 0678dbb..4cec0d9 100644
--- a/core/res/res/drawable-hdpi/scrubber_control_on_pressed_mtrl_alpha.png
+++ b/core/res/res/drawable-hdpi/scrubber_control_on_pressed_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_control_pressed_holo.png b/core/res/res/drawable-hdpi/scrubber_control_pressed_holo.png
index 4dc8999..afc6cbc 100644
--- a/core/res/res/drawable-hdpi/scrubber_control_pressed_holo.png
+++ b/core/res/res/drawable-hdpi/scrubber_control_pressed_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_primary_holo.9.png b/core/res/res/drawable-hdpi/scrubber_primary_holo.9.png
index 260a0a5..94ba89a 100644
--- a/core/res/res/drawable-hdpi/scrubber_primary_holo.9.png
+++ b/core/res/res/drawable-hdpi/scrubber_primary_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_primary_mtrl_alpha.9.png b/core/res/res/drawable-hdpi/scrubber_primary_mtrl_alpha.9.png
index 4cfb1a7..d3a31e1 100644
--- a/core/res/res/drawable-hdpi/scrubber_primary_mtrl_alpha.9.png
+++ b/core/res/res/drawable-hdpi/scrubber_primary_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_secondary_holo.9.png b/core/res/res/drawable-hdpi/scrubber_secondary_holo.9.png
index 09f2d58..c4799c0 100644
--- a/core/res/res/drawable-hdpi/scrubber_secondary_holo.9.png
+++ b/core/res/res/drawable-hdpi/scrubber_secondary_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_track_holo_dark.9.png b/core/res/res/drawable-hdpi/scrubber_track_holo_dark.9.png
index 0c0ccda..a02931b 100644
--- a/core/res/res/drawable-hdpi/scrubber_track_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/scrubber_track_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_track_holo_light.9.png b/core/res/res/drawable-hdpi/scrubber_track_holo_light.9.png
index 90528b1..075913f 100644
--- a/core/res/res/drawable-hdpi/scrubber_track_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/scrubber_track_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_track_mtrl_alpha.9.png b/core/res/res/drawable-hdpi/scrubber_track_mtrl_alpha.9.png
index 32ddf7a..91b5d48 100644
--- a/core/res/res/drawable-hdpi/scrubber_track_mtrl_alpha.9.png
+++ b/core/res/res/drawable-hdpi/scrubber_track_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/search_dropdown_background.9.png b/core/res/res/drawable-hdpi/search_dropdown_background.9.png
index e6945db..cf2ad09 100644
--- a/core/res/res/drawable-hdpi/search_dropdown_background.9.png
+++ b/core/res/res/drawable-hdpi/search_dropdown_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/search_plate.9.png b/core/res/res/drawable-hdpi/search_plate.9.png
index 561c9fa..ace5e88 100644
--- a/core/res/res/drawable-hdpi/search_plate.9.png
+++ b/core/res/res/drawable-hdpi/search_plate.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/search_plate_global.9.png b/core/res/res/drawable-hdpi/search_plate_global.9.png
index 32c6dc3..09a5b5f 100644
--- a/core/res/res/drawable-hdpi/search_plate_global.9.png
+++ b/core/res/res/drawable-hdpi/search_plate_global.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/seek_thumb_normal.png b/core/res/res/drawable-hdpi/seek_thumb_normal.png
index cc83a7d..1183eb1 100644
--- a/core/res/res/drawable-hdpi/seek_thumb_normal.png
+++ b/core/res/res/drawable-hdpi/seek_thumb_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/seek_thumb_pressed.png b/core/res/res/drawable-hdpi/seek_thumb_pressed.png
index 15f79ea..e152a80 100644
--- a/core/res/res/drawable-hdpi/seek_thumb_pressed.png
+++ b/core/res/res/drawable-hdpi/seek_thumb_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/seek_thumb_selected.png b/core/res/res/drawable-hdpi/seek_thumb_selected.png
index 8a7cf68..d1a1132 100644
--- a/core/res/res/drawable-hdpi/seek_thumb_selected.png
+++ b/core/res/res/drawable-hdpi/seek_thumb_selected.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/settings_header_raw.9.png b/core/res/res/drawable-hdpi/settings_header_raw.9.png
index 6857c0f..5fd1a98 100644
--- a/core/res/res/drawable-hdpi/settings_header_raw.9.png
+++ b/core/res/res/drawable-hdpi/settings_header_raw.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sim_dark_blue.9.png b/core/res/res/drawable-hdpi/sim_dark_blue.9.png
index b991535..cb08f95 100644
--- a/core/res/res/drawable-hdpi/sim_dark_blue.9.png
+++ b/core/res/res/drawable-hdpi/sim_dark_blue.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sim_dark_green.9.png b/core/res/res/drawable-hdpi/sim_dark_green.9.png
index c8de61d..e82cf61 100644
--- a/core/res/res/drawable-hdpi/sim_dark_green.9.png
+++ b/core/res/res/drawable-hdpi/sim_dark_green.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sim_dark_orange.9.png b/core/res/res/drawable-hdpi/sim_dark_orange.9.png
index 10347e8..f7e2a60 100644
--- a/core/res/res/drawable-hdpi/sim_dark_orange.9.png
+++ b/core/res/res/drawable-hdpi/sim_dark_orange.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sim_dark_purple.9.png b/core/res/res/drawable-hdpi/sim_dark_purple.9.png
index ac4ee01..2028b94 100644
--- a/core/res/res/drawable-hdpi/sim_dark_purple.9.png
+++ b/core/res/res/drawable-hdpi/sim_dark_purple.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sim_light_blue.9.png b/core/res/res/drawable-hdpi/sim_light_blue.9.png
index b2c5581..6f1d345 100644
--- a/core/res/res/drawable-hdpi/sim_light_blue.9.png
+++ b/core/res/res/drawable-hdpi/sim_light_blue.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sim_light_green.9.png b/core/res/res/drawable-hdpi/sim_light_green.9.png
index 4d29c81..9f03cc6 100644
--- a/core/res/res/drawable-hdpi/sim_light_green.9.png
+++ b/core/res/res/drawable-hdpi/sim_light_green.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sim_light_orange.9.png b/core/res/res/drawable-hdpi/sim_light_orange.9.png
index 68c6c2f..c8be768 100644
--- a/core/res/res/drawable-hdpi/sim_light_orange.9.png
+++ b/core/res/res/drawable-hdpi/sim_light_orange.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sim_light_purple.9.png b/core/res/res/drawable-hdpi/sim_light_purple.9.png
index 4deb8dc5..70ba04a 100644
--- a/core/res/res/drawable-hdpi/sim_light_purple.9.png
+++ b/core/res/res/drawable-hdpi/sim_light_purple.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_16_inner_holo.png b/core/res/res/drawable-hdpi/spinner_16_inner_holo.png
index 383543a..bdcf833 100644
--- a/core/res/res/drawable-hdpi/spinner_16_inner_holo.png
+++ b/core/res/res/drawable-hdpi/spinner_16_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_16_outer_holo.png b/core/res/res/drawable-hdpi/spinner_16_outer_holo.png
index ffdb78a..72a60e3 100644
--- a/core/res/res/drawable-hdpi/spinner_16_outer_holo.png
+++ b/core/res/res/drawable-hdpi/spinner_16_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_48_inner_holo.png b/core/res/res/drawable-hdpi/spinner_48_inner_holo.png
index c8358e9..401378c 100644
--- a/core/res/res/drawable-hdpi/spinner_48_inner_holo.png
+++ b/core/res/res/drawable-hdpi/spinner_48_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_48_outer_holo.png b/core/res/res/drawable-hdpi/spinner_48_outer_holo.png
index f62f74b..af82dd1 100644
--- a/core/res/res/drawable-hdpi/spinner_48_outer_holo.png
+++ b/core/res/res/drawable-hdpi/spinner_48_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_76_inner_holo.png b/core/res/res/drawable-hdpi/spinner_76_inner_holo.png
index c29ab07..f5de566 100644
--- a/core/res/res/drawable-hdpi/spinner_76_inner_holo.png
+++ b/core/res/res/drawable-hdpi/spinner_76_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_76_outer_holo.png b/core/res/res/drawable-hdpi/spinner_76_outer_holo.png
index 287afc6..8444cbe 100644
--- a/core/res/res/drawable-hdpi/spinner_76_outer_holo.png
+++ b/core/res/res/drawable-hdpi/spinner_76_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_ab_default_holo_dark_am.9.png b/core/res/res/drawable-hdpi/spinner_ab_default_holo_dark_am.9.png
index 88f8765..a71ebca 100644
--- a/core/res/res/drawable-hdpi/spinner_ab_default_holo_dark_am.9.png
+++ b/core/res/res/drawable-hdpi/spinner_ab_default_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_ab_default_holo_light_am.9.png b/core/res/res/drawable-hdpi/spinner_ab_default_holo_light_am.9.png
index fa68a13..0f43179 100644
--- a/core/res/res/drawable-hdpi/spinner_ab_default_holo_light_am.9.png
+++ b/core/res/res/drawable-hdpi/spinner_ab_default_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_ab_disabled_holo_dark_am.9.png b/core/res/res/drawable-hdpi/spinner_ab_disabled_holo_dark_am.9.png
index 78c63cb..238beac 100644
--- a/core/res/res/drawable-hdpi/spinner_ab_disabled_holo_dark_am.9.png
+++ b/core/res/res/drawable-hdpi/spinner_ab_disabled_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_ab_disabled_holo_light_am.9.png b/core/res/res/drawable-hdpi/spinner_ab_disabled_holo_light_am.9.png
index e13a9f80..63a37b7 100644
--- a/core/res/res/drawable-hdpi/spinner_ab_disabled_holo_light_am.9.png
+++ b/core/res/res/drawable-hdpi/spinner_ab_disabled_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_ab_focused_holo_dark_am.9.png b/core/res/res/drawable-hdpi/spinner_ab_focused_holo_dark_am.9.png
index 26d2e16..acc2ed5 100644
--- a/core/res/res/drawable-hdpi/spinner_ab_focused_holo_dark_am.9.png
+++ b/core/res/res/drawable-hdpi/spinner_ab_focused_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_ab_focused_holo_light_am.9.png b/core/res/res/drawable-hdpi/spinner_ab_focused_holo_light_am.9.png
index 00ae92a..a211703 100644
--- a/core/res/res/drawable-hdpi/spinner_ab_focused_holo_light_am.9.png
+++ b/core/res/res/drawable-hdpi/spinner_ab_focused_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_dark_am.9.png b/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_dark_am.9.png
index 66f0d88..ad6b6d4 100644
--- a/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_dark_am.9.png
+++ b/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_light_am.9.png b/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_light_am.9.png
index 10af163..8d7e445 100644
--- a/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_light_am.9.png
+++ b/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_black_16.png b/core/res/res/drawable-hdpi/spinner_black_16.png
index ef5ca35..9baa889 100644
--- a/core/res/res/drawable-hdpi/spinner_black_16.png
+++ b/core/res/res/drawable-hdpi/spinner_black_16.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_black_20.png b/core/res/res/drawable-hdpi/spinner_black_20.png
index d938931..7a31c71 100644
--- a/core/res/res/drawable-hdpi/spinner_black_20.png
+++ b/core/res/res/drawable-hdpi/spinner_black_20.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_black_48.png b/core/res/res/drawable-hdpi/spinner_black_48.png
index 9d1efb7..1b2235a 100644
--- a/core/res/res/drawable-hdpi/spinner_black_48.png
+++ b/core/res/res/drawable-hdpi/spinner_black_48.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_black_76.png b/core/res/res/drawable-hdpi/spinner_black_76.png
index 0d90881..b8b0811 100644
--- a/core/res/res/drawable-hdpi/spinner_black_76.png
+++ b/core/res/res/drawable-hdpi/spinner_black_76.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_default_holo_dark_am.9.png b/core/res/res/drawable-hdpi/spinner_default_holo_dark_am.9.png
index 78e583c..7a44456 100644
--- a/core/res/res/drawable-hdpi/spinner_default_holo_dark_am.9.png
+++ b/core/res/res/drawable-hdpi/spinner_default_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_default_holo_light_am.9.png b/core/res/res/drawable-hdpi/spinner_default_holo_light_am.9.png
index fb54f22..91e1685 100644
--- a/core/res/res/drawable-hdpi/spinner_default_holo_light_am.9.png
+++ b/core/res/res/drawable-hdpi/spinner_default_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_disabled_holo_dark_am.9.png b/core/res/res/drawable-hdpi/spinner_disabled_holo_dark_am.9.png
index 210832c..388ad9f 100644
--- a/core/res/res/drawable-hdpi/spinner_disabled_holo_dark_am.9.png
+++ b/core/res/res/drawable-hdpi/spinner_disabled_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_disabled_holo_light_am.9.png b/core/res/res/drawable-hdpi/spinner_disabled_holo_light_am.9.png
index d0d9419..350737a 100644
--- a/core/res/res/drawable-hdpi/spinner_disabled_holo_light_am.9.png
+++ b/core/res/res/drawable-hdpi/spinner_disabled_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_dropdown_background_down.9.png b/core/res/res/drawable-hdpi/spinner_dropdown_background_down.9.png
index 566543d..1f77035 100644
--- a/core/res/res/drawable-hdpi/spinner_dropdown_background_down.9.png
+++ b/core/res/res/drawable-hdpi/spinner_dropdown_background_down.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_dropdown_background_up.9.png b/core/res/res/drawable-hdpi/spinner_dropdown_background_up.9.png
index 7b883cc..41acb20 100644
--- a/core/res/res/drawable-hdpi/spinner_dropdown_background_up.9.png
+++ b/core/res/res/drawable-hdpi/spinner_dropdown_background_up.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_focused_holo_dark_am.9.png b/core/res/res/drawable-hdpi/spinner_focused_holo_dark_am.9.png
index be365ec..f0f6ab9 100644
--- a/core/res/res/drawable-hdpi/spinner_focused_holo_dark_am.9.png
+++ b/core/res/res/drawable-hdpi/spinner_focused_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_focused_holo_light_am.9.png b/core/res/res/drawable-hdpi/spinner_focused_holo_light_am.9.png
index cd7b803..ba1c621 100644
--- a/core/res/res/drawable-hdpi/spinner_focused_holo_light_am.9.png
+++ b/core/res/res/drawable-hdpi/spinner_focused_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_normal.9.png b/core/res/res/drawable-hdpi/spinner_normal.9.png
index b1f25f0..7492568 100644
--- a/core/res/res/drawable-hdpi/spinner_normal.9.png
+++ b/core/res/res/drawable-hdpi/spinner_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_press.9.png b/core/res/res/drawable-hdpi/spinner_press.9.png
index 6aab271..d9d4b84 100644
--- a/core/res/res/drawable-hdpi/spinner_press.9.png
+++ b/core/res/res/drawable-hdpi/spinner_press.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_pressed_holo_dark_am.9.png b/core/res/res/drawable-hdpi/spinner_pressed_holo_dark_am.9.png
index aca9435..24f9d7e 100644
--- a/core/res/res/drawable-hdpi/spinner_pressed_holo_dark_am.9.png
+++ b/core/res/res/drawable-hdpi/spinner_pressed_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_pressed_holo_light_am.9.png b/core/res/res/drawable-hdpi/spinner_pressed_holo_light_am.9.png
index eafd44a..6694128 100644
--- a/core/res/res/drawable-hdpi/spinner_pressed_holo_light_am.9.png
+++ b/core/res/res/drawable-hdpi/spinner_pressed_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_select.9.png b/core/res/res/drawable-hdpi/spinner_select.9.png
index 9024d07..d4fd617 100644
--- a/core/res/res/drawable-hdpi/spinner_select.9.png
+++ b/core/res/res/drawable-hdpi/spinner_select.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_white_16.png b/core/res/res/drawable-hdpi/spinner_white_16.png
index 32fa447..16d908f 100644
--- a/core/res/res/drawable-hdpi/spinner_white_16.png
+++ b/core/res/res/drawable-hdpi/spinner_white_16.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_white_48.png b/core/res/res/drawable-hdpi/spinner_white_48.png
index 31fa267..16677c4 100644
--- a/core/res/res/drawable-hdpi/spinner_white_48.png
+++ b/core/res/res/drawable-hdpi/spinner_white_48.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_white_76.png b/core/res/res/drawable-hdpi/spinner_white_76.png
index 9f63292..65137b2 100644
--- a/core/res/res/drawable-hdpi/spinner_white_76.png
+++ b/core/res/res/drawable-hdpi/spinner_white_76.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/star_big_off.png b/core/res/res/drawable-hdpi/star_big_off.png
index ee6c942..9878c2b 100644
--- a/core/res/res/drawable-hdpi/star_big_off.png
+++ b/core/res/res/drawable-hdpi/star_big_off.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/star_big_on.png b/core/res/res/drawable-hdpi/star_big_on.png
index 17b4d73..4db1588 100644
--- a/core/res/res/drawable-hdpi/star_big_on.png
+++ b/core/res/res/drawable-hdpi/star_big_on.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/star_off.png b/core/res/res/drawable-hdpi/star_off.png
index e1897c7..16b9cb8 100644
--- a/core/res/res/drawable-hdpi/star_off.png
+++ b/core/res/res/drawable-hdpi/star_off.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/star_on.png b/core/res/res/drawable-hdpi/star_on.png
index b7440ea..420420b 100644
--- a/core/res/res/drawable-hdpi/star_on.png
+++ b/core/res/res/drawable-hdpi/star_on.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_ecb_mode.png b/core/res/res/drawable-hdpi/stat_ecb_mode.png
index 91e6c1e..bbf1d9a 100644
--- a/core/res/res/drawable-hdpi/stat_ecb_mode.png
+++ b/core/res/res/drawable-hdpi/stat_ecb_mode.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_car_mode.png b/core/res/res/drawable-hdpi/stat_notify_car_mode.png
index bc6137d..c702a84 100644
--- a/core/res/res/drawable-hdpi/stat_notify_car_mode.png
+++ b/core/res/res/drawable-hdpi/stat_notify_car_mode.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_chat.png b/core/res/res/drawable-hdpi/stat_notify_chat.png
index 32ffdf1..e355e40 100644
--- a/core/res/res/drawable-hdpi/stat_notify_chat.png
+++ b/core/res/res/drawable-hdpi/stat_notify_chat.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_disk_full.png b/core/res/res/drawable-hdpi/stat_notify_disk_full.png
index c696a5b..17cb5dd 100644
--- a/core/res/res/drawable-hdpi/stat_notify_disk_full.png
+++ b/core/res/res/drawable-hdpi/stat_notify_disk_full.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_email_generic.png b/core/res/res/drawable-hdpi/stat_notify_email_generic.png
index c19d667..39027ff 100644
--- a/core/res/res/drawable-hdpi/stat_notify_email_generic.png
+++ b/core/res/res/drawable-hdpi/stat_notify_email_generic.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_error.png b/core/res/res/drawable-hdpi/stat_notify_error.png
index deb3872..f752da8 100644
--- a/core/res/res/drawable-hdpi/stat_notify_error.png
+++ b/core/res/res/drawable-hdpi/stat_notify_error.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_gmail.png b/core/res/res/drawable-hdpi/stat_notify_gmail.png
index f205a7c..276d429 100644
--- a/core/res/res/drawable-hdpi/stat_notify_gmail.png
+++ b/core/res/res/drawable-hdpi/stat_notify_gmail.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_missed_call.png b/core/res/res/drawable-hdpi/stat_notify_missed_call.png
index f205471..b0c116d 100644
--- a/core/res/res/drawable-hdpi/stat_notify_missed_call.png
+++ b/core/res/res/drawable-hdpi/stat_notify_missed_call.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_mmcc_indication_icn.png b/core/res/res/drawable-hdpi/stat_notify_mmcc_indication_icn.png
index d704951..20598b7 100644
--- a/core/res/res/drawable-hdpi/stat_notify_mmcc_indication_icn.png
+++ b/core/res/res/drawable-hdpi/stat_notify_mmcc_indication_icn.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_more.png b/core/res/res/drawable-hdpi/stat_notify_more.png
index f54b3d4..142340a 100644
--- a/core/res/res/drawable-hdpi/stat_notify_more.png
+++ b/core/res/res/drawable-hdpi/stat_notify_more.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_rssi_in_range.png b/core/res/res/drawable-hdpi/stat_notify_rssi_in_range.png
index 74977e6..6adb072 100644
--- a/core/res/res/drawable-hdpi/stat_notify_rssi_in_range.png
+++ b/core/res/res/drawable-hdpi/stat_notify_rssi_in_range.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_sdcard.png b/core/res/res/drawable-hdpi/stat_notify_sdcard.png
index 5892d38..e04ce6a 100644
--- a/core/res/res/drawable-hdpi/stat_notify_sdcard.png
+++ b/core/res/res/drawable-hdpi/stat_notify_sdcard.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_sdcard_prepare.png b/core/res/res/drawable-hdpi/stat_notify_sdcard_prepare.png
index 1c101ea..7afa260 100644
--- a/core/res/res/drawable-hdpi/stat_notify_sdcard_prepare.png
+++ b/core/res/res/drawable-hdpi/stat_notify_sdcard_prepare.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_sdcard_usb.png b/core/res/res/drawable-hdpi/stat_notify_sdcard_usb.png
index 901eac4..9067a10d 100644
--- a/core/res/res/drawable-hdpi/stat_notify_sdcard_usb.png
+++ b/core/res/res/drawable-hdpi/stat_notify_sdcard_usb.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_sim_toolkit.png b/core/res/res/drawable-hdpi/stat_notify_sim_toolkit.png
index a357251..9b57052 100644
--- a/core/res/res/drawable-hdpi/stat_notify_sim_toolkit.png
+++ b/core/res/res/drawable-hdpi/stat_notify_sim_toolkit.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_sync.png b/core/res/res/drawable-hdpi/stat_notify_sync.png
index 90b39c9..2e3928e 100644
--- a/core/res/res/drawable-hdpi/stat_notify_sync.png
+++ b/core/res/res/drawable-hdpi/stat_notify_sync.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_sync_anim0.png b/core/res/res/drawable-hdpi/stat_notify_sync_anim0.png
index 90b39c9..2e3928e 100644
--- a/core/res/res/drawable-hdpi/stat_notify_sync_anim0.png
+++ b/core/res/res/drawable-hdpi/stat_notify_sync_anim0.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_sync_error.png b/core/res/res/drawable-hdpi/stat_notify_sync_error.png
index 074cdee..be40d58 100644
--- a/core/res/res/drawable-hdpi/stat_notify_sync_error.png
+++ b/core/res/res/drawable-hdpi/stat_notify_sync_error.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_voicemail.png b/core/res/res/drawable-hdpi/stat_notify_voicemail.png
index 896d1ce..83787a8 100644
--- a/core/res/res/drawable-hdpi/stat_notify_voicemail.png
+++ b/core/res/res/drawable-hdpi/stat_notify_voicemail.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_battery_0.png b/core/res/res/drawable-hdpi/stat_sys_battery_0.png
index 160a6f7..b5c1a89 100644
--- a/core/res/res/drawable-hdpi/stat_sys_battery_0.png
+++ b/core/res/res/drawable-hdpi/stat_sys_battery_0.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_battery_10.png b/core/res/res/drawable-hdpi/stat_sys_battery_10.png
index 4486553..907c3e3 100644
--- a/core/res/res/drawable-hdpi/stat_sys_battery_10.png
+++ b/core/res/res/drawable-hdpi/stat_sys_battery_10.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_battery_100.png b/core/res/res/drawable-hdpi/stat_sys_battery_100.png
index fa1624c..e5dd8f3 100644
--- a/core/res/res/drawable-hdpi/stat_sys_battery_100.png
+++ b/core/res/res/drawable-hdpi/stat_sys_battery_100.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_battery_15.png b/core/res/res/drawable-hdpi/stat_sys_battery_15.png
index 5d5ac67..dbced37 100644
--- a/core/res/res/drawable-hdpi/stat_sys_battery_15.png
+++ b/core/res/res/drawable-hdpi/stat_sys_battery_15.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_battery_20.png b/core/res/res/drawable-hdpi/stat_sys_battery_20.png
index c8f9c92..def539a 100644
--- a/core/res/res/drawable-hdpi/stat_sys_battery_20.png
+++ b/core/res/res/drawable-hdpi/stat_sys_battery_20.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_battery_28.png b/core/res/res/drawable-hdpi/stat_sys_battery_28.png
index a35ded9..d29c183 100644
--- a/core/res/res/drawable-hdpi/stat_sys_battery_28.png
+++ b/core/res/res/drawable-hdpi/stat_sys_battery_28.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_battery_40.png b/core/res/res/drawable-hdpi/stat_sys_battery_40.png
index 441bbfb..740eea6 100644
--- a/core/res/res/drawable-hdpi/stat_sys_battery_40.png
+++ b/core/res/res/drawable-hdpi/stat_sys_battery_40.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_battery_43.png b/core/res/res/drawable-hdpi/stat_sys_battery_43.png
index b0ea53a..d4e5178 100644
--- a/core/res/res/drawable-hdpi/stat_sys_battery_43.png
+++ b/core/res/res/drawable-hdpi/stat_sys_battery_43.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_battery_57.png b/core/res/res/drawable-hdpi/stat_sys_battery_57.png
index f3c1bd4..9f7195a 100644
--- a/core/res/res/drawable-hdpi/stat_sys_battery_57.png
+++ b/core/res/res/drawable-hdpi/stat_sys_battery_57.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_battery_60.png b/core/res/res/drawable-hdpi/stat_sys_battery_60.png
index d9467ed..83d47a1 100644
--- a/core/res/res/drawable-hdpi/stat_sys_battery_60.png
+++ b/core/res/res/drawable-hdpi/stat_sys_battery_60.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_battery_71.png b/core/res/res/drawable-hdpi/stat_sys_battery_71.png
index 6b3cb32..5763fe7 100644
--- a/core/res/res/drawable-hdpi/stat_sys_battery_71.png
+++ b/core/res/res/drawable-hdpi/stat_sys_battery_71.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_battery_80.png b/core/res/res/drawable-hdpi/stat_sys_battery_80.png
index e3f4805..39e55e8 100644
--- a/core/res/res/drawable-hdpi/stat_sys_battery_80.png
+++ b/core/res/res/drawable-hdpi/stat_sys_battery_80.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_battery_85.png b/core/res/res/drawable-hdpi/stat_sys_battery_85.png
index da3ea72..650d8c7 100644
--- a/core/res/res/drawable-hdpi/stat_sys_battery_85.png
+++ b/core/res/res/drawable-hdpi/stat_sys_battery_85.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim0.png b/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim0.png
index f9f2baf..122516c 100644
--- a/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim0.png
+++ b/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim0.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim1.png b/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim1.png
index 997feb3..1db9ad1 100644
--- a/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim1.png
+++ b/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim1.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim100.png b/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim100.png
index 2bdd813..6131443 100644
--- a/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim100.png
+++ b/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim100.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim15.png b/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim15.png
index 52b8470..a851095 100644
--- a/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim15.png
+++ b/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim15.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim2.png b/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim2.png
index 426a66b..03374a3 100644
--- a/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim2.png
+++ b/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim2.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim28.png b/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim28.png
index 620db05..e3f553b 100644
--- a/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim28.png
+++ b/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim28.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim3.png b/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim3.png
index 21582ca..e3e9c74 100644
--- a/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim3.png
+++ b/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim3.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim4.png b/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim4.png
index 8a94763..71cbd08 100644
--- a/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim4.png
+++ b/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim4.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim43.png b/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim43.png
index bb29a6a..313442e 100644
--- a/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim43.png
+++ b/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim43.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim5.png b/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim5.png
index fad0d65..46d28c4 100644
--- a/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim5.png
+++ b/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim5.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim57.png b/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim57.png
index a417aa3..4df85ee 100644
--- a/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim57.png
+++ b/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim57.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim71.png b/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim71.png
index ab6ed3f..2d2275c 100644
--- a/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim71.png
+++ b/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim71.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim85.png b/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim85.png
index c9961f1..ff0c3f7 100644
--- a/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim85.png
+++ b/core/res/res/drawable-hdpi/stat_sys_battery_charge_anim85.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_battery_unknown.png b/core/res/res/drawable-hdpi/stat_sys_battery_unknown.png
index 368e7d9..a2c8c7c 100644
--- a/core/res/res/drawable-hdpi/stat_sys_battery_unknown.png
+++ b/core/res/res/drawable-hdpi/stat_sys_battery_unknown.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_certificate_info.png b/core/res/res/drawable-hdpi/stat_sys_certificate_info.png
index 3be426c..25ecc4a 100644
--- a/core/res/res/drawable-hdpi/stat_sys_certificate_info.png
+++ b/core/res/res/drawable-hdpi/stat_sys_certificate_info.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_data_bluetooth.png b/core/res/res/drawable-hdpi/stat_sys_data_bluetooth.png
index 8e08f1c..375fb41 100644
--- a/core/res/res/drawable-hdpi/stat_sys_data_bluetooth.png
+++ b/core/res/res/drawable-hdpi/stat_sys_data_bluetooth.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_data_usb.png b/core/res/res/drawable-hdpi/stat_sys_data_usb.png
index f14f908..457d5fc 100644
--- a/core/res/res/drawable-hdpi/stat_sys_data_usb.png
+++ b/core/res/res/drawable-hdpi/stat_sys_data_usb.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_data_wimax_signal_3_fully.png b/core/res/res/drawable-hdpi/stat_sys_data_wimax_signal_3_fully.png
index cb08eed..a82ec70 100644
--- a/core/res/res/drawable-hdpi/stat_sys_data_wimax_signal_3_fully.png
+++ b/core/res/res/drawable-hdpi/stat_sys_data_wimax_signal_3_fully.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_data_wimax_signal_disconnected.png b/core/res/res/drawable-hdpi/stat_sys_data_wimax_signal_disconnected.png
index ea065c3..7c822b99 100644
--- a/core/res/res/drawable-hdpi/stat_sys_data_wimax_signal_disconnected.png
+++ b/core/res/res/drawable-hdpi/stat_sys_data_wimax_signal_disconnected.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_download_anim0.png b/core/res/res/drawable-hdpi/stat_sys_download_anim0.png
index 910de29..db6f3b00 100644
--- a/core/res/res/drawable-hdpi/stat_sys_download_anim0.png
+++ b/core/res/res/drawable-hdpi/stat_sys_download_anim0.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_download_anim1.png b/core/res/res/drawable-hdpi/stat_sys_download_anim1.png
index 0b1aa34..4bf18f1 100644
--- a/core/res/res/drawable-hdpi/stat_sys_download_anim1.png
+++ b/core/res/res/drawable-hdpi/stat_sys_download_anim1.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_download_anim2.png b/core/res/res/drawable-hdpi/stat_sys_download_anim2.png
index bc1877d..aff0bfd5 100644
--- a/core/res/res/drawable-hdpi/stat_sys_download_anim2.png
+++ b/core/res/res/drawable-hdpi/stat_sys_download_anim2.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_download_anim3.png b/core/res/res/drawable-hdpi/stat_sys_download_anim3.png
index 9f41092..cc11e04 100644
--- a/core/res/res/drawable-hdpi/stat_sys_download_anim3.png
+++ b/core/res/res/drawable-hdpi/stat_sys_download_anim3.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_download_anim4.png b/core/res/res/drawable-hdpi/stat_sys_download_anim4.png
index 5fa6305..629d473 100644
--- a/core/res/res/drawable-hdpi/stat_sys_download_anim4.png
+++ b/core/res/res/drawable-hdpi/stat_sys_download_anim4.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_download_anim5.png b/core/res/res/drawable-hdpi/stat_sys_download_anim5.png
index 703759a..be8d6ce 100644
--- a/core/res/res/drawable-hdpi/stat_sys_download_anim5.png
+++ b/core/res/res/drawable-hdpi/stat_sys_download_anim5.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_gps_on.png b/core/res/res/drawable-hdpi/stat_sys_gps_on.png
index e0f7740..dab1c03 100644
--- a/core/res/res/drawable-hdpi/stat_sys_gps_on.png
+++ b/core/res/res/drawable-hdpi/stat_sys_gps_on.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_headset.png b/core/res/res/drawable-hdpi/stat_sys_headset.png
index 7a70aea..4a13e3a 100644
--- a/core/res/res/drawable-hdpi/stat_sys_headset.png
+++ b/core/res/res/drawable-hdpi/stat_sys_headset.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_phone_call.png b/core/res/res/drawable-hdpi/stat_sys_phone_call.png
index 9b5f075..08cfdc9 100644
--- a/core/res/res/drawable-hdpi/stat_sys_phone_call.png
+++ b/core/res/res/drawable-hdpi/stat_sys_phone_call.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_phone_call_forward.png b/core/res/res/drawable-hdpi/stat_sys_phone_call_forward.png
index 032f8f1..b87d508 100644
--- a/core/res/res/drawable-hdpi/stat_sys_phone_call_forward.png
+++ b/core/res/res/drawable-hdpi/stat_sys_phone_call_forward.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_phone_call_on_hold.png b/core/res/res/drawable-hdpi/stat_sys_phone_call_on_hold.png
index 5b0a68d..96b3794 100644
--- a/core/res/res/drawable-hdpi/stat_sys_phone_call_on_hold.png
+++ b/core/res/res/drawable-hdpi/stat_sys_phone_call_on_hold.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_r_signal_0_cdma.png b/core/res/res/drawable-hdpi/stat_sys_r_signal_0_cdma.png
index 14a7e94..ea02663 100644
--- a/core/res/res/drawable-hdpi/stat_sys_r_signal_0_cdma.png
+++ b/core/res/res/drawable-hdpi/stat_sys_r_signal_0_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_r_signal_1_cdma.png b/core/res/res/drawable-hdpi/stat_sys_r_signal_1_cdma.png
index 9cf04b5..1670c86 100644
--- a/core/res/res/drawable-hdpi/stat_sys_r_signal_1_cdma.png
+++ b/core/res/res/drawable-hdpi/stat_sys_r_signal_1_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_r_signal_2_cdma.png b/core/res/res/drawable-hdpi/stat_sys_r_signal_2_cdma.png
index dbd3308..e9c5086 100644
--- a/core/res/res/drawable-hdpi/stat_sys_r_signal_2_cdma.png
+++ b/core/res/res/drawable-hdpi/stat_sys_r_signal_2_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_r_signal_3_cdma.png b/core/res/res/drawable-hdpi/stat_sys_r_signal_3_cdma.png
index a3a6b6c..1af085a 100644
--- a/core/res/res/drawable-hdpi/stat_sys_r_signal_3_cdma.png
+++ b/core/res/res/drawable-hdpi/stat_sys_r_signal_3_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_r_signal_4_cdma.png b/core/res/res/drawable-hdpi/stat_sys_r_signal_4_cdma.png
index 0f95041..e98d097 100644
--- a/core/res/res/drawable-hdpi/stat_sys_r_signal_4_cdma.png
+++ b/core/res/res/drawable-hdpi/stat_sys_r_signal_4_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_ra_signal_0_cdma.png b/core/res/res/drawable-hdpi/stat_sys_ra_signal_0_cdma.png
index a2fa547..07985d8 100644
--- a/core/res/res/drawable-hdpi/stat_sys_ra_signal_0_cdma.png
+++ b/core/res/res/drawable-hdpi/stat_sys_ra_signal_0_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_ra_signal_1_cdma.png b/core/res/res/drawable-hdpi/stat_sys_ra_signal_1_cdma.png
index 17c8681..2f41c08 100644
--- a/core/res/res/drawable-hdpi/stat_sys_ra_signal_1_cdma.png
+++ b/core/res/res/drawable-hdpi/stat_sys_ra_signal_1_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_ra_signal_2_cdma.png b/core/res/res/drawable-hdpi/stat_sys_ra_signal_2_cdma.png
index 4a21fb6..5db2c72 100644
--- a/core/res/res/drawable-hdpi/stat_sys_ra_signal_2_cdma.png
+++ b/core/res/res/drawable-hdpi/stat_sys_ra_signal_2_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_ra_signal_3_cdma.png b/core/res/res/drawable-hdpi/stat_sys_ra_signal_3_cdma.png
index 188b1f9..f5c7d10 100644
--- a/core/res/res/drawable-hdpi/stat_sys_ra_signal_3_cdma.png
+++ b/core/res/res/drawable-hdpi/stat_sys_ra_signal_3_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_ra_signal_4_cdma.png b/core/res/res/drawable-hdpi/stat_sys_ra_signal_4_cdma.png
index 5729f7d..ac68ba5 100644
--- a/core/res/res/drawable-hdpi/stat_sys_ra_signal_4_cdma.png
+++ b/core/res/res/drawable-hdpi/stat_sys_ra_signal_4_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_signal_0_cdma.png b/core/res/res/drawable-hdpi/stat_sys_signal_0_cdma.png
index af43e00..476d1ff 100644
--- a/core/res/res/drawable-hdpi/stat_sys_signal_0_cdma.png
+++ b/core/res/res/drawable-hdpi/stat_sys_signal_0_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_signal_1_cdma.png b/core/res/res/drawable-hdpi/stat_sys_signal_1_cdma.png
index 4ffe421..ff49ed8 100644
--- a/core/res/res/drawable-hdpi/stat_sys_signal_1_cdma.png
+++ b/core/res/res/drawable-hdpi/stat_sys_signal_1_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_signal_2_cdma.png b/core/res/res/drawable-hdpi/stat_sys_signal_2_cdma.png
index 6f27b96..9259fd6 100644
--- a/core/res/res/drawable-hdpi/stat_sys_signal_2_cdma.png
+++ b/core/res/res/drawable-hdpi/stat_sys_signal_2_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_signal_3_cdma.png b/core/res/res/drawable-hdpi/stat_sys_signal_3_cdma.png
index ddc46b0..d309ab4 100644
--- a/core/res/res/drawable-hdpi/stat_sys_signal_3_cdma.png
+++ b/core/res/res/drawable-hdpi/stat_sys_signal_3_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_signal_4_cdma.png b/core/res/res/drawable-hdpi/stat_sys_signal_4_cdma.png
index fb3cfe9..5b90ff5 100644
--- a/core/res/res/drawable-hdpi/stat_sys_signal_4_cdma.png
+++ b/core/res/res/drawable-hdpi/stat_sys_signal_4_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_signal_evdo_0.png b/core/res/res/drawable-hdpi/stat_sys_signal_evdo_0.png
index b697ca4..1108f5d 100644
--- a/core/res/res/drawable-hdpi/stat_sys_signal_evdo_0.png
+++ b/core/res/res/drawable-hdpi/stat_sys_signal_evdo_0.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_signal_evdo_1.png b/core/res/res/drawable-hdpi/stat_sys_signal_evdo_1.png
index a61de4d..d999c72 100644
--- a/core/res/res/drawable-hdpi/stat_sys_signal_evdo_1.png
+++ b/core/res/res/drawable-hdpi/stat_sys_signal_evdo_1.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_signal_evdo_2.png b/core/res/res/drawable-hdpi/stat_sys_signal_evdo_2.png
index 62e0393..d6ceea6 100644
--- a/core/res/res/drawable-hdpi/stat_sys_signal_evdo_2.png
+++ b/core/res/res/drawable-hdpi/stat_sys_signal_evdo_2.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_signal_evdo_3.png b/core/res/res/drawable-hdpi/stat_sys_signal_evdo_3.png
index 09eae9d..e82129d 100644
--- a/core/res/res/drawable-hdpi/stat_sys_signal_evdo_3.png
+++ b/core/res/res/drawable-hdpi/stat_sys_signal_evdo_3.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_signal_evdo_4.png b/core/res/res/drawable-hdpi/stat_sys_signal_evdo_4.png
index 4012ac5..f8fa849 100644
--- a/core/res/res/drawable-hdpi/stat_sys_signal_evdo_4.png
+++ b/core/res/res/drawable-hdpi/stat_sys_signal_evdo_4.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_throttled.png b/core/res/res/drawable-hdpi/stat_sys_throttled.png
index ed66abf..084fb5f 100644
--- a/core/res/res/drawable-hdpi/stat_sys_throttled.png
+++ b/core/res/res/drawable-hdpi/stat_sys_throttled.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_upload_anim0.png b/core/res/res/drawable-hdpi/stat_sys_upload_anim0.png
index 78f54b7..49a7d17 100644
--- a/core/res/res/drawable-hdpi/stat_sys_upload_anim0.png
+++ b/core/res/res/drawable-hdpi/stat_sys_upload_anim0.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_upload_anim1.png b/core/res/res/drawable-hdpi/stat_sys_upload_anim1.png
index 3a9031e..d436c38 100644
--- a/core/res/res/drawable-hdpi/stat_sys_upload_anim1.png
+++ b/core/res/res/drawable-hdpi/stat_sys_upload_anim1.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_upload_anim2.png b/core/res/res/drawable-hdpi/stat_sys_upload_anim2.png
index 39d2c95f..5dc9948 100644
--- a/core/res/res/drawable-hdpi/stat_sys_upload_anim2.png
+++ b/core/res/res/drawable-hdpi/stat_sys_upload_anim2.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_upload_anim3.png b/core/res/res/drawable-hdpi/stat_sys_upload_anim3.png
index 937720f..164347a 100644
--- a/core/res/res/drawable-hdpi/stat_sys_upload_anim3.png
+++ b/core/res/res/drawable-hdpi/stat_sys_upload_anim3.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_upload_anim4.png b/core/res/res/drawable-hdpi/stat_sys_upload_anim4.png
index b35672c..27865ea 100644
--- a/core/res/res/drawable-hdpi/stat_sys_upload_anim4.png
+++ b/core/res/res/drawable-hdpi/stat_sys_upload_anim4.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_upload_anim5.png b/core/res/res/drawable-hdpi/stat_sys_upload_anim5.png
index 4611122..bb21a42 100644
--- a/core/res/res/drawable-hdpi/stat_sys_upload_anim5.png
+++ b/core/res/res/drawable-hdpi/stat_sys_upload_anim5.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_vp_phone_call.png b/core/res/res/drawable-hdpi/stat_sys_vp_phone_call.png
index 83e8ead..74cf4fa 100644
--- a/core/res/res/drawable-hdpi/stat_sys_vp_phone_call.png
+++ b/core/res/res/drawable-hdpi/stat_sys_vp_phone_call.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_vp_phone_call_on_hold.png b/core/res/res/drawable-hdpi/stat_sys_vp_phone_call_on_hold.png
index 9731c46..aedbe04 100644
--- a/core/res/res/drawable-hdpi/stat_sys_vp_phone_call_on_hold.png
+++ b/core/res/res/drawable-hdpi/stat_sys_vp_phone_call_on_hold.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_warning.png b/core/res/res/drawable-hdpi/stat_sys_warning.png
index dbaf944..2dea4bc 100644
--- a/core/res/res/drawable-hdpi/stat_sys_warning.png
+++ b/core/res/res/drawable-hdpi/stat_sys_warning.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/status_bar_background.png b/core/res/res/drawable-hdpi/status_bar_background.png
index 3d00cd0..b189acc 100644
--- a/core/res/res/drawable-hdpi/status_bar_background.png
+++ b/core/res/res/drawable-hdpi/status_bar_background.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/status_bar_header_background.9.png b/core/res/res/drawable-hdpi/status_bar_header_background.9.png
index 37b5fef..0e4b4ab 100644
--- a/core/res/res/drawable-hdpi/status_bar_header_background.9.png
+++ b/core/res/res/drawable-hdpi/status_bar_header_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/status_bar_item_app_background_normal.9.png b/core/res/res/drawable-hdpi/status_bar_item_app_background_normal.9.png
index 4fbfa4f..767cc3d 100644
--- a/core/res/res/drawable-hdpi/status_bar_item_app_background_normal.9.png
+++ b/core/res/res/drawable-hdpi/status_bar_item_app_background_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/status_bar_item_background_focus.9.png b/core/res/res/drawable-hdpi/status_bar_item_background_focus.9.png
index 0876bc6..95c0b2e 100644
--- a/core/res/res/drawable-hdpi/status_bar_item_background_focus.9.png
+++ b/core/res/res/drawable-hdpi/status_bar_item_background_focus.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/status_bar_item_background_normal.9.png b/core/res/res/drawable-hdpi/status_bar_item_background_normal.9.png
index 810c950..15b336a 100644
--- a/core/res/res/drawable-hdpi/status_bar_item_background_normal.9.png
+++ b/core/res/res/drawable-hdpi/status_bar_item_background_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/status_bar_item_background_pressed.9.png b/core/res/res/drawable-hdpi/status_bar_item_background_pressed.9.png
index 343e4ca..c224ab7 100644
--- a/core/res/res/drawable-hdpi/status_bar_item_background_pressed.9.png
+++ b/core/res/res/drawable-hdpi/status_bar_item_background_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/statusbar_background.9.png b/core/res/res/drawable-hdpi/statusbar_background.9.png
index a4be298..fb4b18f 100644
--- a/core/res/res/drawable-hdpi/statusbar_background.9.png
+++ b/core/res/res/drawable-hdpi/statusbar_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/submenu_arrow_nofocus.png b/core/res/res/drawable-hdpi/submenu_arrow_nofocus.png
index afc0891..1bfe35a 100644
--- a/core/res/res/drawable-hdpi/submenu_arrow_nofocus.png
+++ b/core/res/res/drawable-hdpi/submenu_arrow_nofocus.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/switch_bg_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/switch_bg_disabled_holo_dark.9.png
index f2196fd..2e1db7a 100644
--- a/core/res/res/drawable-hdpi/switch_bg_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/switch_bg_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/switch_bg_disabled_holo_light.9.png b/core/res/res/drawable-hdpi/switch_bg_disabled_holo_light.9.png
index f111d82..f91ea85 100644
--- a/core/res/res/drawable-hdpi/switch_bg_disabled_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/switch_bg_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/switch_bg_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/switch_bg_focused_holo_dark.9.png
index 4e2ae0f..944d6ad 100644
--- a/core/res/res/drawable-hdpi/switch_bg_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/switch_bg_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/switch_bg_focused_holo_light.9.png b/core/res/res/drawable-hdpi/switch_bg_focused_holo_light.9.png
index 479e504..87b54b0 100644
--- a/core/res/res/drawable-hdpi/switch_bg_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/switch_bg_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/switch_bg_holo_dark.9.png b/core/res/res/drawable-hdpi/switch_bg_holo_dark.9.png
index 933d99b..93da74f 100644
--- a/core/res/res/drawable-hdpi/switch_bg_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/switch_bg_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/switch_bg_holo_light.9.png b/core/res/res/drawable-hdpi/switch_bg_holo_light.9.png
index 7abe99a..c4807a5 100644
--- a/core/res/res/drawable-hdpi/switch_bg_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/switch_bg_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/switch_thumb_activated_holo_dark.9.png b/core/res/res/drawable-hdpi/switch_thumb_activated_holo_dark.9.png
index 9c5147e..d17e98f 100644
--- a/core/res/res/drawable-hdpi/switch_thumb_activated_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/switch_thumb_activated_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/switch_thumb_activated_holo_light.9.png b/core/res/res/drawable-hdpi/switch_thumb_activated_holo_light.9.png
index 9c5147e..d17e98f 100644
--- a/core/res/res/drawable-hdpi/switch_thumb_activated_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/switch_thumb_activated_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/switch_thumb_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/switch_thumb_disabled_holo_dark.9.png
index a257e26..b3fda99 100644
--- a/core/res/res/drawable-hdpi/switch_thumb_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/switch_thumb_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/switch_thumb_disabled_holo_light.9.png b/core/res/res/drawable-hdpi/switch_thumb_disabled_holo_light.9.png
index a257e26..b3fda99 100644
--- a/core/res/res/drawable-hdpi/switch_thumb_disabled_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/switch_thumb_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/switch_thumb_holo_dark.9.png b/core/res/res/drawable-hdpi/switch_thumb_holo_dark.9.png
index dd999d6..8a3febf 100644
--- a/core/res/res/drawable-hdpi/switch_thumb_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/switch_thumb_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/switch_thumb_holo_light.9.png b/core/res/res/drawable-hdpi/switch_thumb_holo_light.9.png
index dd999d6..8a3febf 100644
--- a/core/res/res/drawable-hdpi/switch_thumb_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/switch_thumb_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/switch_thumb_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/switch_thumb_pressed_holo_dark.9.png
index b6009e6..e030405 100644
--- a/core/res/res/drawable-hdpi/switch_thumb_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/switch_thumb_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/switch_thumb_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/switch_thumb_pressed_holo_light.9.png
index 54d813c..e30211a9 100644
--- a/core/res/res/drawable-hdpi/switch_thumb_pressed_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/switch_thumb_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_action_add.png b/core/res/res/drawable-hdpi/sym_action_add.png
index 6e028b2..9cf27d6 100644
--- a/core/res/res/drawable-hdpi/sym_action_add.png
+++ b/core/res/res/drawable-hdpi/sym_action_add.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_action_call.png b/core/res/res/drawable-hdpi/sym_action_call.png
index da8afee..df6c12c 100644
--- a/core/res/res/drawable-hdpi/sym_action_call.png
+++ b/core/res/res/drawable-hdpi/sym_action_call.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_action_chat.png b/core/res/res/drawable-hdpi/sym_action_chat.png
index 1ed061b..ef407d0 100644
--- a/core/res/res/drawable-hdpi/sym_action_chat.png
+++ b/core/res/res/drawable-hdpi/sym_action_chat.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_action_email.png b/core/res/res/drawable-hdpi/sym_action_email.png
index 1d933e4..6ba88aa 100644
--- a/core/res/res/drawable-hdpi/sym_action_email.png
+++ b/core/res/res/drawable-hdpi/sym_action_email.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_call_incoming.png b/core/res/res/drawable-hdpi/sym_call_incoming.png
index 83c75dc..19d6bd3 100644
--- a/core/res/res/drawable-hdpi/sym_call_incoming.png
+++ b/core/res/res/drawable-hdpi/sym_call_incoming.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_call_missed.png b/core/res/res/drawable-hdpi/sym_call_missed.png
index abcbbbf..2538bc2 100644
--- a/core/res/res/drawable-hdpi/sym_call_missed.png
+++ b/core/res/res/drawable-hdpi/sym_call_missed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_call_outgoing.png b/core/res/res/drawable-hdpi/sym_call_outgoing.png
index 6cb8653..09f8fb1 100644
--- a/core/res/res/drawable-hdpi/sym_call_outgoing.png
+++ b/core/res/res/drawable-hdpi/sym_call_outgoing.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_contact_card.png b/core/res/res/drawable-hdpi/sym_contact_card.png
index fe9c751..0c272e5 100644
--- a/core/res/res/drawable-hdpi/sym_contact_card.png
+++ b/core/res/res/drawable-hdpi/sym_contact_card.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_delete.png b/core/res/res/drawable-hdpi/sym_keyboard_delete.png
index 476d902..e1a4f8b 100644
--- a/core/res/res/drawable-hdpi/sym_keyboard_delete.png
+++ b/core/res/res/drawable-hdpi/sym_keyboard_delete.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_delete_dim.png b/core/res/res/drawable-hdpi/sym_keyboard_delete_dim.png
index 34b6d1f..42338ac 100644
--- a/core/res/res/drawable-hdpi/sym_keyboard_delete_dim.png
+++ b/core/res/res/drawable-hdpi/sym_keyboard_delete_dim.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_enter.png b/core/res/res/drawable-hdpi/sym_keyboard_enter.png
index d118af2..5ad7315 100644
--- a/core/res/res/drawable-hdpi/sym_keyboard_enter.png
+++ b/core/res/res/drawable-hdpi/sym_keyboard_enter.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_feedback_delete.png b/core/res/res/drawable-hdpi/sym_keyboard_feedback_delete.png
index ca76375..9ae66d2 100644
--- a/core/res/res/drawable-hdpi/sym_keyboard_feedback_delete.png
+++ b/core/res/res/drawable-hdpi/sym_keyboard_feedback_delete.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_feedback_ok.png b/core/res/res/drawable-hdpi/sym_keyboard_feedback_ok.png
index 2d144ec..f2fc505 100644
--- a/core/res/res/drawable-hdpi/sym_keyboard_feedback_ok.png
+++ b/core/res/res/drawable-hdpi/sym_keyboard_feedback_ok.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_feedback_return.png b/core/res/res/drawable-hdpi/sym_keyboard_feedback_return.png
index ae57299..dfc1696 100644
--- a/core/res/res/drawable-hdpi/sym_keyboard_feedback_return.png
+++ b/core/res/res/drawable-hdpi/sym_keyboard_feedback_return.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_feedback_shift.png b/core/res/res/drawable-hdpi/sym_keyboard_feedback_shift.png
index 4db31c8..0e2b25a 100644
--- a/core/res/res/drawable-hdpi/sym_keyboard_feedback_shift.png
+++ b/core/res/res/drawable-hdpi/sym_keyboard_feedback_shift.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_feedback_shift_locked.png b/core/res/res/drawable-hdpi/sym_keyboard_feedback_shift_locked.png
index 3fd5659..44005dc 100644
--- a/core/res/res/drawable-hdpi/sym_keyboard_feedback_shift_locked.png
+++ b/core/res/res/drawable-hdpi/sym_keyboard_feedback_shift_locked.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_feedback_space.png b/core/res/res/drawable-hdpi/sym_keyboard_feedback_space.png
index 98266ee..71c69a5 100644
--- a/core/res/res/drawable-hdpi/sym_keyboard_feedback_space.png
+++ b/core/res/res/drawable-hdpi/sym_keyboard_feedback_space.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_num0_no_plus.png b/core/res/res/drawable-hdpi/sym_keyboard_num0_no_plus.png
index ad81bb3..c478e1a 100644
--- a/core/res/res/drawable-hdpi/sym_keyboard_num0_no_plus.png
+++ b/core/res/res/drawable-hdpi/sym_keyboard_num0_no_plus.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_num1.png b/core/res/res/drawable-hdpi/sym_keyboard_num1.png
index 8d2468c..e127e38 100644
--- a/core/res/res/drawable-hdpi/sym_keyboard_num1.png
+++ b/core/res/res/drawable-hdpi/sym_keyboard_num1.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_num2.png b/core/res/res/drawable-hdpi/sym_keyboard_num2.png
index cfa972b..cd3a6ed 100644
--- a/core/res/res/drawable-hdpi/sym_keyboard_num2.png
+++ b/core/res/res/drawable-hdpi/sym_keyboard_num2.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_num3.png b/core/res/res/drawable-hdpi/sym_keyboard_num3.png
index 141833a..1b1b959 100644
--- a/core/res/res/drawable-hdpi/sym_keyboard_num3.png
+++ b/core/res/res/drawable-hdpi/sym_keyboard_num3.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_num4.png b/core/res/res/drawable-hdpi/sym_keyboard_num4.png
index 07df14d..922b573 100644
--- a/core/res/res/drawable-hdpi/sym_keyboard_num4.png
+++ b/core/res/res/drawable-hdpi/sym_keyboard_num4.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_num5.png b/core/res/res/drawable-hdpi/sym_keyboard_num5.png
index fbcc9bf..4e34187 100644
--- a/core/res/res/drawable-hdpi/sym_keyboard_num5.png
+++ b/core/res/res/drawable-hdpi/sym_keyboard_num5.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_num6.png b/core/res/res/drawable-hdpi/sym_keyboard_num6.png
index 9513b33..ebf2d6d 100644
--- a/core/res/res/drawable-hdpi/sym_keyboard_num6.png
+++ b/core/res/res/drawable-hdpi/sym_keyboard_num6.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_num7.png b/core/res/res/drawable-hdpi/sym_keyboard_num7.png
index 5ad25d8..b25a3f3 100644
--- a/core/res/res/drawable-hdpi/sym_keyboard_num7.png
+++ b/core/res/res/drawable-hdpi/sym_keyboard_num7.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_num8.png b/core/res/res/drawable-hdpi/sym_keyboard_num8.png
index 97d5c0e..3cccb5a 100644
--- a/core/res/res/drawable-hdpi/sym_keyboard_num8.png
+++ b/core/res/res/drawable-hdpi/sym_keyboard_num8.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_num9.png b/core/res/res/drawable-hdpi/sym_keyboard_num9.png
index a7d6a83..e544874 100644
--- a/core/res/res/drawable-hdpi/sym_keyboard_num9.png
+++ b/core/res/res/drawable-hdpi/sym_keyboard_num9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_ok.png b/core/res/res/drawable-hdpi/sym_keyboard_ok.png
index 9105da2..d234292 100644
--- a/core/res/res/drawable-hdpi/sym_keyboard_ok.png
+++ b/core/res/res/drawable-hdpi/sym_keyboard_ok.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_ok_dim.png b/core/res/res/drawable-hdpi/sym_keyboard_ok_dim.png
index bd419de..73e5b16 100644
--- a/core/res/res/drawable-hdpi/sym_keyboard_ok_dim.png
+++ b/core/res/res/drawable-hdpi/sym_keyboard_ok_dim.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_return.png b/core/res/res/drawable-hdpi/sym_keyboard_return.png
index 58505c5..79d277c 100644
--- a/core/res/res/drawable-hdpi/sym_keyboard_return.png
+++ b/core/res/res/drawable-hdpi/sym_keyboard_return.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_shift.png b/core/res/res/drawable-hdpi/sym_keyboard_shift.png
index 8149081..88af750 100644
--- a/core/res/res/drawable-hdpi/sym_keyboard_shift.png
+++ b/core/res/res/drawable-hdpi/sym_keyboard_shift.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_shift_locked.png b/core/res/res/drawable-hdpi/sym_keyboard_shift_locked.png
index 31ca277..ce3473d0 100644
--- a/core/res/res/drawable-hdpi/sym_keyboard_shift_locked.png
+++ b/core/res/res/drawable-hdpi/sym_keyboard_shift_locked.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sym_keyboard_space.png b/core/res/res/drawable-hdpi/sym_keyboard_space.png
index 3e98b30..8e43ebf 100644
--- a/core/res/res/drawable-hdpi/sym_keyboard_space.png
+++ b/core/res/res/drawable-hdpi/sym_keyboard_space.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_bottom_holo.9.png b/core/res/res/drawable-hdpi/tab_bottom_holo.9.png
index 8abf2ba..1179ccc 100644
--- a/core/res/res/drawable-hdpi/tab_bottom_holo.9.png
+++ b/core/res/res/drawable-hdpi/tab_bottom_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_focus.9.png b/core/res/res/drawable-hdpi/tab_focus.9.png
index 8862fc7..e5196ac 100644
--- a/core/res/res/drawable-hdpi/tab_focus.9.png
+++ b/core/res/res/drawable-hdpi/tab_focus.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_focus_bar_left.9.png b/core/res/res/drawable-hdpi/tab_focus_bar_left.9.png
index 7f40d36..129be84 100644
--- a/core/res/res/drawable-hdpi/tab_focus_bar_left.9.png
+++ b/core/res/res/drawable-hdpi/tab_focus_bar_left.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_focus_bar_right.9.png b/core/res/res/drawable-hdpi/tab_focus_bar_right.9.png
index 7f40d36..d083261 100644
--- a/core/res/res/drawable-hdpi/tab_focus_bar_right.9.png
+++ b/core/res/res/drawable-hdpi/tab_focus_bar_right.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_indicator_mtrl_alpha.9.png b/core/res/res/drawable-hdpi/tab_indicator_mtrl_alpha.9.png
index 21b2135..a59f548 100644
--- a/core/res/res/drawable-hdpi/tab_indicator_mtrl_alpha.9.png
+++ b/core/res/res/drawable-hdpi/tab_indicator_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_press.9.png b/core/res/res/drawable-hdpi/tab_press.9.png
index 4650d68..3ab0228 100644
--- a/core/res/res/drawable-hdpi/tab_press.9.png
+++ b/core/res/res/drawable-hdpi/tab_press.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_press_bar_left.9.png b/core/res/res/drawable-hdpi/tab_press_bar_left.9.png
index b43c592..c44a47d 100644
--- a/core/res/res/drawable-hdpi/tab_press_bar_left.9.png
+++ b/core/res/res/drawable-hdpi/tab_press_bar_left.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_press_bar_right.9.png b/core/res/res/drawable-hdpi/tab_press_bar_right.9.png
index b43c592..c44a47d 100644
--- a/core/res/res/drawable-hdpi/tab_press_bar_right.9.png
+++ b/core/res/res/drawable-hdpi/tab_press_bar_right.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_pressed_holo.9.png b/core/res/res/drawable-hdpi/tab_pressed_holo.9.png
index 6d05735..026b973 100644
--- a/core/res/res/drawable-hdpi/tab_pressed_holo.9.png
+++ b/core/res/res/drawable-hdpi/tab_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_selected.9.png b/core/res/res/drawable-hdpi/tab_selected.9.png
index d5d3cee..635f981 100644
--- a/core/res/res/drawable-hdpi/tab_selected.9.png
+++ b/core/res/res/drawable-hdpi/tab_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_selected_bar_left.9.png b/core/res/res/drawable-hdpi/tab_selected_bar_left.9.png
index c1f950c..eef6889 100644
--- a/core/res/res/drawable-hdpi/tab_selected_bar_left.9.png
+++ b/core/res/res/drawable-hdpi/tab_selected_bar_left.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_selected_bar_left_v4.9.png b/core/res/res/drawable-hdpi/tab_selected_bar_left_v4.9.png
index e7a07255..92cd997 100644
--- a/core/res/res/drawable-hdpi/tab_selected_bar_left_v4.9.png
+++ b/core/res/res/drawable-hdpi/tab_selected_bar_left_v4.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_selected_bar_right.9.png b/core/res/res/drawable-hdpi/tab_selected_bar_right.9.png
index c1f950c..eef6889 100644
--- a/core/res/res/drawable-hdpi/tab_selected_bar_right.9.png
+++ b/core/res/res/drawable-hdpi/tab_selected_bar_right.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_selected_bar_right_v4.9.png b/core/res/res/drawable-hdpi/tab_selected_bar_right_v4.9.png
index e7a07255..92cd997 100644
--- a/core/res/res/drawable-hdpi/tab_selected_bar_right_v4.9.png
+++ b/core/res/res/drawable-hdpi/tab_selected_bar_right_v4.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_selected_focused_holo.9.png b/core/res/res/drawable-hdpi/tab_selected_focused_holo.9.png
index 673e3bf..53c379e 100644
--- a/core/res/res/drawable-hdpi/tab_selected_focused_holo.9.png
+++ b/core/res/res/drawable-hdpi/tab_selected_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_selected_holo.9.png b/core/res/res/drawable-hdpi/tab_selected_holo.9.png
index d57df98..e9a01ad 100644
--- a/core/res/res/drawable-hdpi/tab_selected_holo.9.png
+++ b/core/res/res/drawable-hdpi/tab_selected_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_selected_pressed_holo.9.png b/core/res/res/drawable-hdpi/tab_selected_pressed_holo.9.png
index 956d3c4..db4d3f4 100644
--- a/core/res/res/drawable-hdpi/tab_selected_pressed_holo.9.png
+++ b/core/res/res/drawable-hdpi/tab_selected_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_selected_v4.9.png b/core/res/res/drawable-hdpi/tab_selected_v4.9.png
index 50fcb52..bf9e94b 100644
--- a/core/res/res/drawable-hdpi/tab_selected_v4.9.png
+++ b/core/res/res/drawable-hdpi/tab_selected_v4.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_unselected.9.png b/core/res/res/drawable-hdpi/tab_unselected.9.png
index cdc7a4a..8ff02be 100644
--- a/core/res/res/drawable-hdpi/tab_unselected.9.png
+++ b/core/res/res/drawable-hdpi/tab_unselected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_unselected_focused_holo.9.png b/core/res/res/drawable-hdpi/tab_unselected_focused_holo.9.png
index 294991d..4d6e907 100644
--- a/core/res/res/drawable-hdpi/tab_unselected_focused_holo.9.png
+++ b/core/res/res/drawable-hdpi/tab_unselected_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_unselected_holo.9.png b/core/res/res/drawable-hdpi/tab_unselected_holo.9.png
index 19532ab..4bdaec7 100644
--- a/core/res/res/drawable-hdpi/tab_unselected_holo.9.png
+++ b/core/res/res/drawable-hdpi/tab_unselected_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_unselected_pressed_holo.9.png b/core/res/res/drawable-hdpi/tab_unselected_pressed_holo.9.png
index 57e57e1..5bd48be 100644
--- a/core/res/res/drawable-hdpi/tab_unselected_pressed_holo.9.png
+++ b/core/res/res/drawable-hdpi/tab_unselected_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_unselected_v4.9.png b/core/res/res/drawable-hdpi/tab_unselected_v4.9.png
index c56254c..794b84e 100644
--- a/core/res/res/drawable-hdpi/tab_unselected_v4.9.png
+++ b/core/res/res/drawable-hdpi/tab_unselected_v4.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_edit_paste_window.9.png b/core/res/res/drawable-hdpi/text_edit_paste_window.9.png
index 8a64d36..cb7a514 100644
--- a/core/res/res/drawable-hdpi/text_edit_paste_window.9.png
+++ b/core/res/res/drawable-hdpi/text_edit_paste_window.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_edit_side_paste_window.9.png b/core/res/res/drawable-hdpi/text_edit_side_paste_window.9.png
index 2b50efa..abca758 100644
--- a/core/res/res/drawable-hdpi/text_edit_side_paste_window.9.png
+++ b/core/res/res/drawable-hdpi/text_edit_side_paste_window.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_edit_suggestions_window.9.png b/core/res/res/drawable-hdpi/text_edit_suggestions_window.9.png
index 8a64d36..cb7a514 100644
--- a/core/res/res/drawable-hdpi/text_edit_suggestions_window.9.png
+++ b/core/res/res/drawable-hdpi/text_edit_suggestions_window.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_select_handle_left_mtrl_alpha.png b/core/res/res/drawable-hdpi/text_select_handle_left_mtrl_alpha.png
index 7ccb70a..8c3ca53 100644
--- a/core/res/res/drawable-hdpi/text_select_handle_left_mtrl_alpha.png
+++ b/core/res/res/drawable-hdpi/text_select_handle_left_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_select_handle_middle_mtrl_alpha.png b/core/res/res/drawable-hdpi/text_select_handle_middle_mtrl_alpha.png
index df2fdb8..ec9f448 100644
--- a/core/res/res/drawable-hdpi/text_select_handle_middle_mtrl_alpha.png
+++ b/core/res/res/drawable-hdpi/text_select_handle_middle_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_select_handle_right_mtrl_alpha.png b/core/res/res/drawable-hdpi/text_select_handle_right_mtrl_alpha.png
index e65b89d..8fae7d5 100644
--- a/core/res/res/drawable-hdpi/text_select_handle_right_mtrl_alpha.png
+++ b/core/res/res/drawable-hdpi/text_select_handle_right_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_activated_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_activated_holo_dark.9.png
index b7c5dcd..7aab0f5 100644
--- a/core/res/res/drawable-hdpi/textfield_activated_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_activated_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_activated_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_activated_holo_light.9.png
index 1aaa9ae..7aab0f5 100644
--- a/core/res/res/drawable-hdpi/textfield_activated_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/textfield_activated_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_activated_mtrl_alpha.9.png b/core/res/res/drawable-hdpi/textfield_activated_mtrl_alpha.9.png
index 9501e7c..e754aef 100644
--- a/core/res/res/drawable-hdpi/textfield_activated_mtrl_alpha.9.png
+++ b/core/res/res/drawable-hdpi/textfield_activated_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_bg_activated_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_bg_activated_holo_dark.9.png
index a233b0d..b5946e1 100644
--- a/core/res/res/drawable-hdpi/textfield_bg_activated_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_bg_activated_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_bg_default_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_bg_default_holo_dark.9.png
index 403f502..77adfe7 100644
--- a/core/res/res/drawable-hdpi/textfield_bg_default_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_bg_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_bg_disabled_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_bg_disabled_focused_holo_dark.9.png
index 0ded801..aad40c9 100644
--- a/core/res/res/drawable-hdpi/textfield_bg_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_bg_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_bg_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_bg_disabled_holo_dark.9.png
index 27237b8..685e1d6 100644
--- a/core/res/res/drawable-hdpi/textfield_bg_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_bg_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_bg_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_bg_focused_holo_dark.9.png
index 0e451f1..07c7620 100644
--- a/core/res/res/drawable-hdpi/textfield_bg_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_bg_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_default.9.png b/core/res/res/drawable-hdpi/textfield_default.9.png
index f7b6e99..f9f885b 100644
--- a/core/res/res/drawable-hdpi/textfield_default.9.png
+++ b/core/res/res/drawable-hdpi/textfield_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_default_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_default_holo_dark.9.png
index e6ef296..ecd8f57 100644
--- a/core/res/res/drawable-hdpi/textfield_default_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_default_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_default_holo_light.9.png
index 7368261..fc86b30 100644
--- a/core/res/res/drawable-hdpi/textfield_default_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/textfield_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_default_mtrl_alpha.9.png b/core/res/res/drawable-hdpi/textfield_default_mtrl_alpha.9.png
index de5572d..b2bc48c 100644
--- a/core/res/res/drawable-hdpi/textfield_default_mtrl_alpha.9.png
+++ b/core/res/res/drawable-hdpi/textfield_default_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_disabled.9.png b/core/res/res/drawable-hdpi/textfield_disabled.9.png
index 3011502..bc2accd 100644
--- a/core/res/res/drawable-hdpi/textfield_disabled.9.png
+++ b/core/res/res/drawable-hdpi/textfield_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_disabled_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_disabled_focused_holo_dark.9.png
index 29e33e3..7a2f281 100644
--- a/core/res/res/drawable-hdpi/textfield_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_disabled_focused_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_disabled_focused_holo_light.9.png
index b70db4e..e39d5c3 100644
--- a/core/res/res/drawable-hdpi/textfield_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/textfield_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_disabled_holo_dark.9.png
index 73ec37c..ee040a3 100644
--- a/core/res/res/drawable-hdpi/textfield_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_disabled_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_disabled_holo_light.9.png
index a77d66d..17e97a1 100644
--- a/core/res/res/drawable-hdpi/textfield_disabled_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/textfield_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_disabled_selected.9.png b/core/res/res/drawable-hdpi/textfield_disabled_selected.9.png
index e0f82eb..2dfb27f 100644
--- a/core/res/res/drawable-hdpi/textfield_disabled_selected.9.png
+++ b/core/res/res/drawable-hdpi/textfield_disabled_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_focused_holo_dark.9.png
index 03a81d9..3e18be4 100644
--- a/core/res/res/drawable-hdpi/textfield_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_focused_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_focused_holo_light.9.png
index 03a81d9..3e18be4 100644
--- a/core/res/res/drawable-hdpi/textfield_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/textfield_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_longpress_holo.9.png b/core/res/res/drawable-hdpi/textfield_longpress_holo.9.png
index 2993b44..32b1444 100644
--- a/core/res/res/drawable-hdpi/textfield_longpress_holo.9.png
+++ b/core/res/res/drawable-hdpi/textfield_longpress_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_multiline_activated_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_multiline_activated_holo_dark.9.png
index 3141caf..7aab0f5 100644
--- a/core/res/res/drawable-hdpi/textfield_multiline_activated_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_multiline_activated_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_multiline_activated_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_multiline_activated_holo_light.9.png
index df7f7708..7aab0f5 100644
--- a/core/res/res/drawable-hdpi/textfield_multiline_activated_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/textfield_multiline_activated_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_multiline_default_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_multiline_default_holo_dark.9.png
index ab381a6..ecd8f57 100644
--- a/core/res/res/drawable-hdpi/textfield_multiline_default_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_multiline_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_multiline_default_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_multiline_default_holo_light.9.png
index ed1306c..fc86b30 100644
--- a/core/res/res/drawable-hdpi/textfield_multiline_default_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/textfield_multiline_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_multiline_disabled_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_multiline_disabled_focused_holo_dark.9.png
index 269e6b3..7a2f281 100644
--- a/core/res/res/drawable-hdpi/textfield_multiline_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_multiline_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_multiline_disabled_focused_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_multiline_disabled_focused_holo_light.9.png
index e0a83fe..e39d5c3 100644
--- a/core/res/res/drawable-hdpi/textfield_multiline_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/textfield_multiline_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_multiline_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_multiline_disabled_holo_dark.9.png
index 9f14a06..ee040a3 100644
--- a/core/res/res/drawable-hdpi/textfield_multiline_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_multiline_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_multiline_disabled_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_multiline_disabled_holo_light.9.png
index c458698..17e97a1 100644
--- a/core/res/res/drawable-hdpi/textfield_multiline_disabled_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/textfield_multiline_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_multiline_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_multiline_focused_holo_dark.9.png
index 180d85c..9fb10c0 100644
--- a/core/res/res/drawable-hdpi/textfield_multiline_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_multiline_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_multiline_focused_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_multiline_focused_holo_light.9.png
index e075149..9fb10c0 100644
--- a/core/res/res/drawable-hdpi/textfield_multiline_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/textfield_multiline_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_pressed_holo.9.png b/core/res/res/drawable-hdpi/textfield_pressed_holo.9.png
index 4aad237..22d9d92 100644
--- a/core/res/res/drawable-hdpi/textfield_pressed_holo.9.png
+++ b/core/res/res/drawable-hdpi/textfield_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_activated_mtrl_alpha.9.png b/core/res/res/drawable-hdpi/textfield_search_activated_mtrl_alpha.9.png
index ce577e5..1ea56ff 100644
--- a/core/res/res/drawable-hdpi/textfield_search_activated_mtrl_alpha.9.png
+++ b/core/res/res/drawable-hdpi/textfield_search_activated_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_default.9.png b/core/res/res/drawable-hdpi/textfield_search_default.9.png
index db64da1..4739fb5 100644
--- a/core/res/res/drawable-hdpi/textfield_search_default.9.png
+++ b/core/res/res/drawable-hdpi/textfield_search_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_default_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_search_default_holo_dark.9.png
index 70c0e73..a31d0ff 100644
--- a/core/res/res/drawable-hdpi/textfield_search_default_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_search_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_default_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_search_default_holo_light.9.png
index 36e71d8..ddd4d2d 100644
--- a/core/res/res/drawable-hdpi/textfield_search_default_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/textfield_search_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_default_mtrl_alpha.9.png b/core/res/res/drawable-hdpi/textfield_search_default_mtrl_alpha.9.png
index 7c305ab..f2d15d4 100644
--- a/core/res/res/drawable-hdpi/textfield_search_default_mtrl_alpha.9.png
+++ b/core/res/res/drawable-hdpi/textfield_search_default_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_empty_default.9.png b/core/res/res/drawable-hdpi/textfield_search_empty_default.9.png
index c0b84da..1a04925 100644
--- a/core/res/res/drawable-hdpi/textfield_search_empty_default.9.png
+++ b/core/res/res/drawable-hdpi/textfield_search_empty_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_empty_pressed.9.png b/core/res/res/drawable-hdpi/textfield_search_empty_pressed.9.png
index 0a0fc6b..7cdf51e 100644
--- a/core/res/res/drawable-hdpi/textfield_search_empty_pressed.9.png
+++ b/core/res/res/drawable-hdpi/textfield_search_empty_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_empty_selected.9.png b/core/res/res/drawable-hdpi/textfield_search_empty_selected.9.png
index 04813c2..66fac4b 100644
--- a/core/res/res/drawable-hdpi/textfield_search_empty_selected.9.png
+++ b/core/res/res/drawable-hdpi/textfield_search_empty_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_pressed.9.png b/core/res/res/drawable-hdpi/textfield_search_pressed.9.png
index cde51e4..01a4c86 100644
--- a/core/res/res/drawable-hdpi/textfield_search_pressed.9.png
+++ b/core/res/res/drawable-hdpi/textfield_search_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_right_default_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_search_right_default_holo_dark.9.png
index 4be4af5f..72833b7 100644
--- a/core/res/res/drawable-hdpi/textfield_search_right_default_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_search_right_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_right_default_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_search_right_default_holo_light.9.png
index e72193f..24ebc60 100644
--- a/core/res/res/drawable-hdpi/textfield_search_right_default_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/textfield_search_right_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_right_selected_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_search_right_selected_holo_dark.9.png
index 8f20b9d2..9929454 100644
--- a/core/res/res/drawable-hdpi/textfield_search_right_selected_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_search_right_selected_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_right_selected_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_search_right_selected_holo_light.9.png
index 04f657e..96678b0 100644
--- a/core/res/res/drawable-hdpi/textfield_search_right_selected_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/textfield_search_right_selected_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_selected.9.png b/core/res/res/drawable-hdpi/textfield_search_selected.9.png
index f4bf352..a55d7c7 100644
--- a/core/res/res/drawable-hdpi/textfield_search_selected.9.png
+++ b/core/res/res/drawable-hdpi/textfield_search_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_selected_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_search_selected_holo_dark.9.png
index 99309ef..d81423a 100644
--- a/core/res/res/drawable-hdpi/textfield_search_selected_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_search_selected_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_selected_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_search_selected_holo_light.9.png
index 9bde7fb..6130b48 100644
--- a/core/res/res/drawable-hdpi/textfield_search_selected_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/textfield_search_selected_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_selected.9.png b/core/res/res/drawable-hdpi/textfield_selected.9.png
index cf2cae3..496e18d 100644
--- a/core/res/res/drawable-hdpi/textfield_selected.9.png
+++ b/core/res/res/drawable-hdpi/textfield_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/title_bar_medium.9.png b/core/res/res/drawable-hdpi/title_bar_medium.9.png
index 311a54a..e8593c0 100644
--- a/core/res/res/drawable-hdpi/title_bar_medium.9.png
+++ b/core/res/res/drawable-hdpi/title_bar_medium.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/title_bar_portrait.9.png b/core/res/res/drawable-hdpi/title_bar_portrait.9.png
index 70f7cc2..a48cd6e 100644
--- a/core/res/res/drawable-hdpi/title_bar_portrait.9.png
+++ b/core/res/res/drawable-hdpi/title_bar_portrait.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/title_bar_tall.9.png b/core/res/res/drawable-hdpi/title_bar_tall.9.png
index 5c1a69f..91a111a 100644
--- a/core/res/res/drawable-hdpi/title_bar_tall.9.png
+++ b/core/res/res/drawable-hdpi/title_bar_tall.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/transportcontrol_bg.9.png b/core/res/res/drawable-hdpi/transportcontrol_bg.9.png
index ebd6f8a..0307987 100644
--- a/core/res/res/drawable-hdpi/transportcontrol_bg.9.png
+++ b/core/res/res/drawable-hdpi/transportcontrol_bg.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/unknown_image.png b/core/res/res/drawable-hdpi/unknown_image.png
index 76341db..4ca4599b 100644
--- a/core/res/res/drawable-hdpi/unknown_image.png
+++ b/core/res/res/drawable-hdpi/unknown_image.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_14w.png b/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_14w.png
index 371469c..035e901 100644
--- a/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_14w.png
+++ b/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_14w.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_15w.png b/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_15w.png
index e477260..6688631 100644
--- a/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_15w.png
+++ b/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_15w.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_16w.png b/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_16w.png
index 19a1bd3..a8398f6 100644
--- a/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_16w.png
+++ b/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_16w.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_17w.png b/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_17w.png
index 79dc733..a15b133 100644
--- a/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_17w.png
+++ b/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_17w.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_18w.png b/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_18w.png
index 6d921c0..1cd259e 100644
--- a/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_18w.png
+++ b/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_18w.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/watch_switch_track_mtrl.png b/core/res/res/drawable-hdpi/watch_switch_track_mtrl.png
index ecee3e1..b5c49bb 100644
--- a/core/res/res/drawable-hdpi/watch_switch_track_mtrl.png
+++ b/core/res/res/drawable-hdpi/watch_switch_track_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/zoom_plate.9.png b/core/res/res/drawable-hdpi/zoom_plate.9.png
index e97dac1..c0ba60fa 100644
--- a/core/res/res/drawable-hdpi/zoom_plate.9.png
+++ b/core/res/res/drawable-hdpi/zoom_plate.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/btn_lock_normal.9.png b/core/res/res/drawable-land-hdpi/btn_lock_normal.9.png
index f1dac62..801a082 100644
--- a/core/res/res/drawable-land-hdpi/btn_lock_normal.9.png
+++ b/core/res/res/drawable-land-hdpi/btn_lock_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_bar_left_end_confirm_gray.9.png b/core/res/res/drawable-land-hdpi/jog_tab_bar_left_end_confirm_gray.9.png
index 76f76bc..6d19205 100644
--- a/core/res/res/drawable-land-hdpi/jog_tab_bar_left_end_confirm_gray.9.png
+++ b/core/res/res/drawable-land-hdpi/jog_tab_bar_left_end_confirm_gray.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_bar_left_end_confirm_green.9.png b/core/res/res/drawable-land-hdpi/jog_tab_bar_left_end_confirm_green.9.png
index d070fad..3a5238c 100644
--- a/core/res/res/drawable-land-hdpi/jog_tab_bar_left_end_confirm_green.9.png
+++ b/core/res/res/drawable-land-hdpi/jog_tab_bar_left_end_confirm_green.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_bar_left_end_confirm_red.9.png b/core/res/res/drawable-land-hdpi/jog_tab_bar_left_end_confirm_red.9.png
index 8d38ea6..909a592 100644
--- a/core/res/res/drawable-land-hdpi/jog_tab_bar_left_end_confirm_red.9.png
+++ b/core/res/res/drawable-land-hdpi/jog_tab_bar_left_end_confirm_red.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_bar_left_end_confirm_yellow.9.png b/core/res/res/drawable-land-hdpi/jog_tab_bar_left_end_confirm_yellow.9.png
index 2da4677..d7e66d0 100644
--- a/core/res/res/drawable-land-hdpi/jog_tab_bar_left_end_confirm_yellow.9.png
+++ b/core/res/res/drawable-land-hdpi/jog_tab_bar_left_end_confirm_yellow.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_bar_left_end_normal.9.png b/core/res/res/drawable-land-hdpi/jog_tab_bar_left_end_normal.9.png
index a181652..2fbb8be 100644
--- a/core/res/res/drawable-land-hdpi/jog_tab_bar_left_end_normal.9.png
+++ b/core/res/res/drawable-land-hdpi/jog_tab_bar_left_end_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_bar_left_end_pressed.9.png b/core/res/res/drawable-land-hdpi/jog_tab_bar_left_end_pressed.9.png
index 6cf3131..e6609c9 100644
--- a/core/res/res/drawable-land-hdpi/jog_tab_bar_left_end_pressed.9.png
+++ b/core/res/res/drawable-land-hdpi/jog_tab_bar_left_end_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_bar_right_end_confirm_gray.9.png b/core/res/res/drawable-land-hdpi/jog_tab_bar_right_end_confirm_gray.9.png
index 05541f3..1ef577d 100644
--- a/core/res/res/drawable-land-hdpi/jog_tab_bar_right_end_confirm_gray.9.png
+++ b/core/res/res/drawable-land-hdpi/jog_tab_bar_right_end_confirm_gray.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_bar_right_end_confirm_green.9.png b/core/res/res/drawable-land-hdpi/jog_tab_bar_right_end_confirm_green.9.png
index 0bf0ea9..bbe7512 100644
--- a/core/res/res/drawable-land-hdpi/jog_tab_bar_right_end_confirm_green.9.png
+++ b/core/res/res/drawable-land-hdpi/jog_tab_bar_right_end_confirm_green.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_bar_right_end_confirm_red.9.png b/core/res/res/drawable-land-hdpi/jog_tab_bar_right_end_confirm_red.9.png
index b82a30f..c208b74 100644
--- a/core/res/res/drawable-land-hdpi/jog_tab_bar_right_end_confirm_red.9.png
+++ b/core/res/res/drawable-land-hdpi/jog_tab_bar_right_end_confirm_red.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_bar_right_end_confirm_yellow.9.png b/core/res/res/drawable-land-hdpi/jog_tab_bar_right_end_confirm_yellow.9.png
index 5f530fa..be05ec1 100644
--- a/core/res/res/drawable-land-hdpi/jog_tab_bar_right_end_confirm_yellow.9.png
+++ b/core/res/res/drawable-land-hdpi/jog_tab_bar_right_end_confirm_yellow.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_bar_right_end_normal.9.png b/core/res/res/drawable-land-hdpi/jog_tab_bar_right_end_normal.9.png
index d8bbd17..2dc6869 100644
--- a/core/res/res/drawable-land-hdpi/jog_tab_bar_right_end_normal.9.png
+++ b/core/res/res/drawable-land-hdpi/jog_tab_bar_right_end_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_bar_right_end_pressed.9.png b/core/res/res/drawable-land-hdpi/jog_tab_bar_right_end_pressed.9.png
index c408087..7c23ea7 100644
--- a/core/res/res/drawable-land-hdpi/jog_tab_bar_right_end_pressed.9.png
+++ b/core/res/res/drawable-land-hdpi/jog_tab_bar_right_end_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_left_confirm_gray.png b/core/res/res/drawable-land-hdpi/jog_tab_left_confirm_gray.png
index dff38b4..8b2cd2a 100644
--- a/core/res/res/drawable-land-hdpi/jog_tab_left_confirm_gray.png
+++ b/core/res/res/drawable-land-hdpi/jog_tab_left_confirm_gray.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_left_confirm_green.png b/core/res/res/drawable-land-hdpi/jog_tab_left_confirm_green.png
index 88a95be..0984099 100644
--- a/core/res/res/drawable-land-hdpi/jog_tab_left_confirm_green.png
+++ b/core/res/res/drawable-land-hdpi/jog_tab_left_confirm_green.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_left_confirm_red.png b/core/res/res/drawable-land-hdpi/jog_tab_left_confirm_red.png
index b9486ea..18789ec 100644
--- a/core/res/res/drawable-land-hdpi/jog_tab_left_confirm_red.png
+++ b/core/res/res/drawable-land-hdpi/jog_tab_left_confirm_red.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_left_confirm_yellow.png b/core/res/res/drawable-land-hdpi/jog_tab_left_confirm_yellow.png
index 9144d7a..86801d3 100644
--- a/core/res/res/drawable-land-hdpi/jog_tab_left_confirm_yellow.png
+++ b/core/res/res/drawable-land-hdpi/jog_tab_left_confirm_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_left_normal.png b/core/res/res/drawable-land-hdpi/jog_tab_left_normal.png
index b2d7695..ae7283c 100644
--- a/core/res/res/drawable-land-hdpi/jog_tab_left_normal.png
+++ b/core/res/res/drawable-land-hdpi/jog_tab_left_normal.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_left_pressed.png b/core/res/res/drawable-land-hdpi/jog_tab_left_pressed.png
index 55e170d..cb7275e 100644
--- a/core/res/res/drawable-land-hdpi/jog_tab_left_pressed.png
+++ b/core/res/res/drawable-land-hdpi/jog_tab_left_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_right_confirm_gray.png b/core/res/res/drawable-land-hdpi/jog_tab_right_confirm_gray.png
index 131b720..1a22fba 100644
--- a/core/res/res/drawable-land-hdpi/jog_tab_right_confirm_gray.png
+++ b/core/res/res/drawable-land-hdpi/jog_tab_right_confirm_gray.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_right_confirm_green.png b/core/res/res/drawable-land-hdpi/jog_tab_right_confirm_green.png
index c36b0ad..b57bd9d 100644
--- a/core/res/res/drawable-land-hdpi/jog_tab_right_confirm_green.png
+++ b/core/res/res/drawable-land-hdpi/jog_tab_right_confirm_green.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_right_confirm_red.png b/core/res/res/drawable-land-hdpi/jog_tab_right_confirm_red.png
index d388619..c6ef0cf 100644
--- a/core/res/res/drawable-land-hdpi/jog_tab_right_confirm_red.png
+++ b/core/res/res/drawable-land-hdpi/jog_tab_right_confirm_red.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_right_confirm_yellow.png b/core/res/res/drawable-land-hdpi/jog_tab_right_confirm_yellow.png
index 24f1aec..6f5eb4d 100644
--- a/core/res/res/drawable-land-hdpi/jog_tab_right_confirm_yellow.png
+++ b/core/res/res/drawable-land-hdpi/jog_tab_right_confirm_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_right_normal.png b/core/res/res/drawable-land-hdpi/jog_tab_right_normal.png
index 9111649..41676ee 100644
--- a/core/res/res/drawable-land-hdpi/jog_tab_right_normal.png
+++ b/core/res/res/drawable-land-hdpi/jog_tab_right_normal.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_right_pressed.png b/core/res/res/drawable-land-hdpi/jog_tab_right_pressed.png
index 3bd2e5b..4c4f9b5 100644
--- a/core/res/res/drawable-land-hdpi/jog_tab_right_pressed.png
+++ b/core/res/res/drawable-land-hdpi/jog_tab_right_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_target_gray.png b/core/res/res/drawable-land-hdpi/jog_tab_target_gray.png
index 4150007..f0a46cb 100644
--- a/core/res/res/drawable-land-hdpi/jog_tab_target_gray.png
+++ b/core/res/res/drawable-land-hdpi/jog_tab_target_gray.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_target_green.png b/core/res/res/drawable-land-hdpi/jog_tab_target_green.png
index ef18b6c..7432387 100644
--- a/core/res/res/drawable-land-hdpi/jog_tab_target_green.png
+++ b/core/res/res/drawable-land-hdpi/jog_tab_target_green.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_target_red.png b/core/res/res/drawable-land-hdpi/jog_tab_target_red.png
index 5dfaa5f..28fec48 100644
--- a/core/res/res/drawable-land-hdpi/jog_tab_target_red.png
+++ b/core/res/res/drawable-land-hdpi/jog_tab_target_red.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_target_yellow.png b/core/res/res/drawable-land-hdpi/jog_tab_target_yellow.png
index d0509fa..33a9b08 100644
--- a/core/res/res/drawable-land-hdpi/jog_tab_target_yellow.png
+++ b/core/res/res/drawable-land-hdpi/jog_tab_target_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-land-ldpi/btn_lock_normal.9.png b/core/res/res/drawable-land-ldpi/btn_lock_normal.9.png
index e685adc..fc19577 100644
--- a/core/res/res/drawable-land-ldpi/btn_lock_normal.9.png
+++ b/core/res/res/drawable-land-ldpi/btn_lock_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-ldpi/ic_jog_dial_sound_off.png b/core/res/res/drawable-land-ldpi/ic_jog_dial_sound_off.png
index a4e3edf..f9d418a 100644
--- a/core/res/res/drawable-land-ldpi/ic_jog_dial_sound_off.png
+++ b/core/res/res/drawable-land-ldpi/ic_jog_dial_sound_off.png
Binary files differ
diff --git a/core/res/res/drawable-land-ldpi/ic_jog_dial_sound_on.png b/core/res/res/drawable-land-ldpi/ic_jog_dial_sound_on.png
index f8190b56..7e53177 100644
--- a/core/res/res/drawable-land-ldpi/ic_jog_dial_sound_on.png
+++ b/core/res/res/drawable-land-ldpi/ic_jog_dial_sound_on.png
Binary files differ
diff --git a/core/res/res/drawable-land-ldpi/ic_jog_dial_unlock.png b/core/res/res/drawable-land-ldpi/ic_jog_dial_unlock.png
index 16fa0db..2d5d691c 100644
--- a/core/res/res/drawable-land-ldpi/ic_jog_dial_unlock.png
+++ b/core/res/res/drawable-land-ldpi/ic_jog_dial_unlock.png
Binary files differ
diff --git a/core/res/res/drawable-land-ldpi/jog_tab_bar_left_end_confirm_gray.9.png b/core/res/res/drawable-land-ldpi/jog_tab_bar_left_end_confirm_gray.9.png
index e16e9f6..0949660 100644
--- a/core/res/res/drawable-land-ldpi/jog_tab_bar_left_end_confirm_gray.9.png
+++ b/core/res/res/drawable-land-ldpi/jog_tab_bar_left_end_confirm_gray.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-ldpi/jog_tab_bar_left_end_confirm_green.9.png b/core/res/res/drawable-land-ldpi/jog_tab_bar_left_end_confirm_green.9.png
index 90211df..43ea0d0 100644
--- a/core/res/res/drawable-land-ldpi/jog_tab_bar_left_end_confirm_green.9.png
+++ b/core/res/res/drawable-land-ldpi/jog_tab_bar_left_end_confirm_green.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-ldpi/jog_tab_bar_left_end_confirm_red.9.png b/core/res/res/drawable-land-ldpi/jog_tab_bar_left_end_confirm_red.9.png
index 154ae8e..8d3f7e9 100644
--- a/core/res/res/drawable-land-ldpi/jog_tab_bar_left_end_confirm_red.9.png
+++ b/core/res/res/drawable-land-ldpi/jog_tab_bar_left_end_confirm_red.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-ldpi/jog_tab_bar_left_end_confirm_yellow.9.png b/core/res/res/drawable-land-ldpi/jog_tab_bar_left_end_confirm_yellow.9.png
index 1e69e4d..a60d84f 100644
--- a/core/res/res/drawable-land-ldpi/jog_tab_bar_left_end_confirm_yellow.9.png
+++ b/core/res/res/drawable-land-ldpi/jog_tab_bar_left_end_confirm_yellow.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-ldpi/jog_tab_bar_left_end_normal.9.png b/core/res/res/drawable-land-ldpi/jog_tab_bar_left_end_normal.9.png
index 09710a5..72acb51 100644
--- a/core/res/res/drawable-land-ldpi/jog_tab_bar_left_end_normal.9.png
+++ b/core/res/res/drawable-land-ldpi/jog_tab_bar_left_end_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-ldpi/jog_tab_bar_left_end_pressed.9.png b/core/res/res/drawable-land-ldpi/jog_tab_bar_left_end_pressed.9.png
index 158ce85..ecd4a70 100644
--- a/core/res/res/drawable-land-ldpi/jog_tab_bar_left_end_pressed.9.png
+++ b/core/res/res/drawable-land-ldpi/jog_tab_bar_left_end_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-ldpi/jog_tab_bar_right_end_confirm_gray.9.png b/core/res/res/drawable-land-ldpi/jog_tab_bar_right_end_confirm_gray.9.png
index 1be54d4..4d062d4 100644
--- a/core/res/res/drawable-land-ldpi/jog_tab_bar_right_end_confirm_gray.9.png
+++ b/core/res/res/drawable-land-ldpi/jog_tab_bar_right_end_confirm_gray.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-ldpi/jog_tab_bar_right_end_confirm_green.9.png b/core/res/res/drawable-land-ldpi/jog_tab_bar_right_end_confirm_green.9.png
index 4ef4d69..5c6d18a 100644
--- a/core/res/res/drawable-land-ldpi/jog_tab_bar_right_end_confirm_green.9.png
+++ b/core/res/res/drawable-land-ldpi/jog_tab_bar_right_end_confirm_green.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-ldpi/jog_tab_bar_right_end_confirm_red.9.png b/core/res/res/drawable-land-ldpi/jog_tab_bar_right_end_confirm_red.9.png
index dad283e..c841c453 100644
--- a/core/res/res/drawable-land-ldpi/jog_tab_bar_right_end_confirm_red.9.png
+++ b/core/res/res/drawable-land-ldpi/jog_tab_bar_right_end_confirm_red.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-ldpi/jog_tab_bar_right_end_confirm_yellow.9.png b/core/res/res/drawable-land-ldpi/jog_tab_bar_right_end_confirm_yellow.9.png
index f7aa85a..c4d0866 100644
--- a/core/res/res/drawable-land-ldpi/jog_tab_bar_right_end_confirm_yellow.9.png
+++ b/core/res/res/drawable-land-ldpi/jog_tab_bar_right_end_confirm_yellow.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-ldpi/jog_tab_bar_right_end_normal.9.png b/core/res/res/drawable-land-ldpi/jog_tab_bar_right_end_normal.9.png
index 23860ce..8bc1bd6 100644
--- a/core/res/res/drawable-land-ldpi/jog_tab_bar_right_end_normal.9.png
+++ b/core/res/res/drawable-land-ldpi/jog_tab_bar_right_end_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-ldpi/jog_tab_bar_right_end_pressed.9.png b/core/res/res/drawable-land-ldpi/jog_tab_bar_right_end_pressed.9.png
index 1105fe5..09e639f 100644
--- a/core/res/res/drawable-land-ldpi/jog_tab_bar_right_end_pressed.9.png
+++ b/core/res/res/drawable-land-ldpi/jog_tab_bar_right_end_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-ldpi/jog_tab_left_confirm_gray.png b/core/res/res/drawable-land-ldpi/jog_tab_left_confirm_gray.png
index 945851d..d798c0c3 100644
--- a/core/res/res/drawable-land-ldpi/jog_tab_left_confirm_gray.png
+++ b/core/res/res/drawable-land-ldpi/jog_tab_left_confirm_gray.png
Binary files differ
diff --git a/core/res/res/drawable-land-ldpi/jog_tab_left_confirm_green.png b/core/res/res/drawable-land-ldpi/jog_tab_left_confirm_green.png
index 0702927..1166dce 100644
--- a/core/res/res/drawable-land-ldpi/jog_tab_left_confirm_green.png
+++ b/core/res/res/drawable-land-ldpi/jog_tab_left_confirm_green.png
Binary files differ
diff --git a/core/res/res/drawable-land-ldpi/jog_tab_left_confirm_red.png b/core/res/res/drawable-land-ldpi/jog_tab_left_confirm_red.png
index d79f46c..07aa1bf 100644
--- a/core/res/res/drawable-land-ldpi/jog_tab_left_confirm_red.png
+++ b/core/res/res/drawable-land-ldpi/jog_tab_left_confirm_red.png
Binary files differ
diff --git a/core/res/res/drawable-land-ldpi/jog_tab_left_confirm_yellow.png b/core/res/res/drawable-land-ldpi/jog_tab_left_confirm_yellow.png
index 8e4ef9a..8657bb9 100644
--- a/core/res/res/drawable-land-ldpi/jog_tab_left_confirm_yellow.png
+++ b/core/res/res/drawable-land-ldpi/jog_tab_left_confirm_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-land-ldpi/jog_tab_left_normal.png b/core/res/res/drawable-land-ldpi/jog_tab_left_normal.png
index ee6d98c..b8ad58d 100644
--- a/core/res/res/drawable-land-ldpi/jog_tab_left_normal.png
+++ b/core/res/res/drawable-land-ldpi/jog_tab_left_normal.png
Binary files differ
diff --git a/core/res/res/drawable-land-ldpi/jog_tab_left_pressed.png b/core/res/res/drawable-land-ldpi/jog_tab_left_pressed.png
index 727fdbb..75ca06b 100644
--- a/core/res/res/drawable-land-ldpi/jog_tab_left_pressed.png
+++ b/core/res/res/drawable-land-ldpi/jog_tab_left_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-land-ldpi/jog_tab_right_confirm_gray.png b/core/res/res/drawable-land-ldpi/jog_tab_right_confirm_gray.png
index 93d0bf4..721ed8d 100644
--- a/core/res/res/drawable-land-ldpi/jog_tab_right_confirm_gray.png
+++ b/core/res/res/drawable-land-ldpi/jog_tab_right_confirm_gray.png
Binary files differ
diff --git a/core/res/res/drawable-land-ldpi/jog_tab_right_confirm_green.png b/core/res/res/drawable-land-ldpi/jog_tab_right_confirm_green.png
index d49c831..9b7ada8 100644
--- a/core/res/res/drawable-land-ldpi/jog_tab_right_confirm_green.png
+++ b/core/res/res/drawable-land-ldpi/jog_tab_right_confirm_green.png
Binary files differ
diff --git a/core/res/res/drawable-land-ldpi/jog_tab_right_confirm_red.png b/core/res/res/drawable-land-ldpi/jog_tab_right_confirm_red.png
index 29bddcf..831c109 100644
--- a/core/res/res/drawable-land-ldpi/jog_tab_right_confirm_red.png
+++ b/core/res/res/drawable-land-ldpi/jog_tab_right_confirm_red.png
Binary files differ
diff --git a/core/res/res/drawable-land-ldpi/jog_tab_right_confirm_yellow.png b/core/res/res/drawable-land-ldpi/jog_tab_right_confirm_yellow.png
index 4cefb0c..d50b8b3 100644
--- a/core/res/res/drawable-land-ldpi/jog_tab_right_confirm_yellow.png
+++ b/core/res/res/drawable-land-ldpi/jog_tab_right_confirm_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-land-ldpi/jog_tab_right_normal.png b/core/res/res/drawable-land-ldpi/jog_tab_right_normal.png
index 30fa002..e12c291 100644
--- a/core/res/res/drawable-land-ldpi/jog_tab_right_normal.png
+++ b/core/res/res/drawable-land-ldpi/jog_tab_right_normal.png
Binary files differ
diff --git a/core/res/res/drawable-land-ldpi/jog_tab_right_pressed.png b/core/res/res/drawable-land-ldpi/jog_tab_right_pressed.png
index f2d358b..e000fcf 100644
--- a/core/res/res/drawable-land-ldpi/jog_tab_right_pressed.png
+++ b/core/res/res/drawable-land-ldpi/jog_tab_right_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-land-ldpi/jog_tab_target_gray.png b/core/res/res/drawable-land-ldpi/jog_tab_target_gray.png
index 1e76bc1..76490ce 100644
--- a/core/res/res/drawable-land-ldpi/jog_tab_target_gray.png
+++ b/core/res/res/drawable-land-ldpi/jog_tab_target_gray.png
Binary files differ
diff --git a/core/res/res/drawable-land-ldpi/jog_tab_target_green.png b/core/res/res/drawable-land-ldpi/jog_tab_target_green.png
index 917769e..3c29bbd 100644
--- a/core/res/res/drawable-land-ldpi/jog_tab_target_green.png
+++ b/core/res/res/drawable-land-ldpi/jog_tab_target_green.png
Binary files differ
diff --git a/core/res/res/drawable-land-ldpi/jog_tab_target_red.png b/core/res/res/drawable-land-ldpi/jog_tab_target_red.png
index 3501ba38..82444b5 100644
--- a/core/res/res/drawable-land-ldpi/jog_tab_target_red.png
+++ b/core/res/res/drawable-land-ldpi/jog_tab_target_red.png
Binary files differ
diff --git a/core/res/res/drawable-land-ldpi/jog_tab_target_yellow.png b/core/res/res/drawable-land-ldpi/jog_tab_target_yellow.png
index ee795a3..e3f7c59 100644
--- a/core/res/res/drawable-land-ldpi/jog_tab_target_yellow.png
+++ b/core/res/res/drawable-land-ldpi/jog_tab_target_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-land-mdpi/btn_lock_normal.9.png b/core/res/res/drawable-land-mdpi/btn_lock_normal.9.png
index f2482c0..e6a36d7 100644
--- a/core/res/res/drawable-land-mdpi/btn_lock_normal.9.png
+++ b/core/res/res/drawable-land-mdpi/btn_lock_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-mdpi/jog_tab_bar_left_end_confirm_gray.9.png b/core/res/res/drawable-land-mdpi/jog_tab_bar_left_end_confirm_gray.9.png
index 61222f4..ee83af8 100644
--- a/core/res/res/drawable-land-mdpi/jog_tab_bar_left_end_confirm_gray.9.png
+++ b/core/res/res/drawable-land-mdpi/jog_tab_bar_left_end_confirm_gray.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-mdpi/jog_tab_bar_left_end_confirm_green.9.png b/core/res/res/drawable-land-mdpi/jog_tab_bar_left_end_confirm_green.9.png
index 3060f72..cf9c874 100644
--- a/core/res/res/drawable-land-mdpi/jog_tab_bar_left_end_confirm_green.9.png
+++ b/core/res/res/drawable-land-mdpi/jog_tab_bar_left_end_confirm_green.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-mdpi/jog_tab_bar_left_end_confirm_red.9.png b/core/res/res/drawable-land-mdpi/jog_tab_bar_left_end_confirm_red.9.png
index cee7bf5..cd7eb21 100644
--- a/core/res/res/drawable-land-mdpi/jog_tab_bar_left_end_confirm_red.9.png
+++ b/core/res/res/drawable-land-mdpi/jog_tab_bar_left_end_confirm_red.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-mdpi/jog_tab_bar_left_end_confirm_yellow.9.png b/core/res/res/drawable-land-mdpi/jog_tab_bar_left_end_confirm_yellow.9.png
index 4bd56d1..aa5feb2 100644
--- a/core/res/res/drawable-land-mdpi/jog_tab_bar_left_end_confirm_yellow.9.png
+++ b/core/res/res/drawable-land-mdpi/jog_tab_bar_left_end_confirm_yellow.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-mdpi/jog_tab_bar_left_end_normal.9.png b/core/res/res/drawable-land-mdpi/jog_tab_bar_left_end_normal.9.png
index 367e887..08cadd5 100644
--- a/core/res/res/drawable-land-mdpi/jog_tab_bar_left_end_normal.9.png
+++ b/core/res/res/drawable-land-mdpi/jog_tab_bar_left_end_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-mdpi/jog_tab_bar_left_end_pressed.9.png b/core/res/res/drawable-land-mdpi/jog_tab_bar_left_end_pressed.9.png
index 02f3f27..e896ed3 100644
--- a/core/res/res/drawable-land-mdpi/jog_tab_bar_left_end_pressed.9.png
+++ b/core/res/res/drawable-land-mdpi/jog_tab_bar_left_end_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-mdpi/jog_tab_bar_right_end_confirm_gray.9.png b/core/res/res/drawable-land-mdpi/jog_tab_bar_right_end_confirm_gray.9.png
index bfaba2f..dee8602 100644
--- a/core/res/res/drawable-land-mdpi/jog_tab_bar_right_end_confirm_gray.9.png
+++ b/core/res/res/drawable-land-mdpi/jog_tab_bar_right_end_confirm_gray.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-mdpi/jog_tab_bar_right_end_confirm_green.9.png b/core/res/res/drawable-land-mdpi/jog_tab_bar_right_end_confirm_green.9.png
index d35fe7b..ad5cd5d 100644
--- a/core/res/res/drawable-land-mdpi/jog_tab_bar_right_end_confirm_green.9.png
+++ b/core/res/res/drawable-land-mdpi/jog_tab_bar_right_end_confirm_green.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-mdpi/jog_tab_bar_right_end_confirm_red.9.png b/core/res/res/drawable-land-mdpi/jog_tab_bar_right_end_confirm_red.9.png
index 508f6bd..a9b8429 100644
--- a/core/res/res/drawable-land-mdpi/jog_tab_bar_right_end_confirm_red.9.png
+++ b/core/res/res/drawable-land-mdpi/jog_tab_bar_right_end_confirm_red.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-mdpi/jog_tab_bar_right_end_confirm_yellow.9.png b/core/res/res/drawable-land-mdpi/jog_tab_bar_right_end_confirm_yellow.9.png
index a6041e5..b089564 100644
--- a/core/res/res/drawable-land-mdpi/jog_tab_bar_right_end_confirm_yellow.9.png
+++ b/core/res/res/drawable-land-mdpi/jog_tab_bar_right_end_confirm_yellow.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-mdpi/jog_tab_bar_right_end_normal.9.png b/core/res/res/drawable-land-mdpi/jog_tab_bar_right_end_normal.9.png
index 28cdd0b..86c65ce 100644
--- a/core/res/res/drawable-land-mdpi/jog_tab_bar_right_end_normal.9.png
+++ b/core/res/res/drawable-land-mdpi/jog_tab_bar_right_end_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-mdpi/jog_tab_bar_right_end_pressed.9.png b/core/res/res/drawable-land-mdpi/jog_tab_bar_right_end_pressed.9.png
index 46ba76b..d2f44dd9 100644
--- a/core/res/res/drawable-land-mdpi/jog_tab_bar_right_end_pressed.9.png
+++ b/core/res/res/drawable-land-mdpi/jog_tab_bar_right_end_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-mdpi/jog_tab_left_confirm_gray.png b/core/res/res/drawable-land-mdpi/jog_tab_left_confirm_gray.png
index 396dcf7..aa6a763 100644
--- a/core/res/res/drawable-land-mdpi/jog_tab_left_confirm_gray.png
+++ b/core/res/res/drawable-land-mdpi/jog_tab_left_confirm_gray.png
Binary files differ
diff --git a/core/res/res/drawable-land-mdpi/jog_tab_left_confirm_green.png b/core/res/res/drawable-land-mdpi/jog_tab_left_confirm_green.png
index d928310..3b9009b 100644
--- a/core/res/res/drawable-land-mdpi/jog_tab_left_confirm_green.png
+++ b/core/res/res/drawable-land-mdpi/jog_tab_left_confirm_green.png
Binary files differ
diff --git a/core/res/res/drawable-land-mdpi/jog_tab_left_confirm_red.png b/core/res/res/drawable-land-mdpi/jog_tab_left_confirm_red.png
index c377463..2354a68 100644
--- a/core/res/res/drawable-land-mdpi/jog_tab_left_confirm_red.png
+++ b/core/res/res/drawable-land-mdpi/jog_tab_left_confirm_red.png
Binary files differ
diff --git a/core/res/res/drawable-land-mdpi/jog_tab_left_confirm_yellow.png b/core/res/res/drawable-land-mdpi/jog_tab_left_confirm_yellow.png
index b868c76..2851220 100644
--- a/core/res/res/drawable-land-mdpi/jog_tab_left_confirm_yellow.png
+++ b/core/res/res/drawable-land-mdpi/jog_tab_left_confirm_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-land-mdpi/jog_tab_left_normal.png b/core/res/res/drawable-land-mdpi/jog_tab_left_normal.png
index 5ca876b..fdb790e 100644
--- a/core/res/res/drawable-land-mdpi/jog_tab_left_normal.png
+++ b/core/res/res/drawable-land-mdpi/jog_tab_left_normal.png
Binary files differ
diff --git a/core/res/res/drawable-land-mdpi/jog_tab_left_pressed.png b/core/res/res/drawable-land-mdpi/jog_tab_left_pressed.png
index 8c33a78..afec815 100644
--- a/core/res/res/drawable-land-mdpi/jog_tab_left_pressed.png
+++ b/core/res/res/drawable-land-mdpi/jog_tab_left_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-land-mdpi/jog_tab_right_confirm_gray.png b/core/res/res/drawable-land-mdpi/jog_tab_right_confirm_gray.png
index 4f1a002..cba9449 100644
--- a/core/res/res/drawable-land-mdpi/jog_tab_right_confirm_gray.png
+++ b/core/res/res/drawable-land-mdpi/jog_tab_right_confirm_gray.png
Binary files differ
diff --git a/core/res/res/drawable-land-mdpi/jog_tab_right_confirm_green.png b/core/res/res/drawable-land-mdpi/jog_tab_right_confirm_green.png
index af1550f..3ef8d9a 100644
--- a/core/res/res/drawable-land-mdpi/jog_tab_right_confirm_green.png
+++ b/core/res/res/drawable-land-mdpi/jog_tab_right_confirm_green.png
Binary files differ
diff --git a/core/res/res/drawable-land-mdpi/jog_tab_right_confirm_red.png b/core/res/res/drawable-land-mdpi/jog_tab_right_confirm_red.png
index b458d27..f6f672b 100644
--- a/core/res/res/drawable-land-mdpi/jog_tab_right_confirm_red.png
+++ b/core/res/res/drawable-land-mdpi/jog_tab_right_confirm_red.png
Binary files differ
diff --git a/core/res/res/drawable-land-mdpi/jog_tab_right_confirm_yellow.png b/core/res/res/drawable-land-mdpi/jog_tab_right_confirm_yellow.png
index 8e55d6a..16790c7 100644
--- a/core/res/res/drawable-land-mdpi/jog_tab_right_confirm_yellow.png
+++ b/core/res/res/drawable-land-mdpi/jog_tab_right_confirm_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-land-mdpi/jog_tab_right_normal.png b/core/res/res/drawable-land-mdpi/jog_tab_right_normal.png
index c607c7c..2f85e59 100644
--- a/core/res/res/drawable-land-mdpi/jog_tab_right_normal.png
+++ b/core/res/res/drawable-land-mdpi/jog_tab_right_normal.png
Binary files differ
diff --git a/core/res/res/drawable-land-mdpi/jog_tab_right_pressed.png b/core/res/res/drawable-land-mdpi/jog_tab_right_pressed.png
index 2537d73..162b246 100644
--- a/core/res/res/drawable-land-mdpi/jog_tab_right_pressed.png
+++ b/core/res/res/drawable-land-mdpi/jog_tab_right_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-land-mdpi/jog_tab_target_gray.png b/core/res/res/drawable-land-mdpi/jog_tab_target_gray.png
index 1319b6e..c0b0a60 100644
--- a/core/res/res/drawable-land-mdpi/jog_tab_target_gray.png
+++ b/core/res/res/drawable-land-mdpi/jog_tab_target_gray.png
Binary files differ
diff --git a/core/res/res/drawable-land-mdpi/jog_tab_target_green.png b/core/res/res/drawable-land-mdpi/jog_tab_target_green.png
index 88a3f30..e1cf10b 100644
--- a/core/res/res/drawable-land-mdpi/jog_tab_target_green.png
+++ b/core/res/res/drawable-land-mdpi/jog_tab_target_green.png
Binary files differ
diff --git a/core/res/res/drawable-land-mdpi/jog_tab_target_red.png b/core/res/res/drawable-land-mdpi/jog_tab_target_red.png
index 300c401..da4654e 100644
--- a/core/res/res/drawable-land-mdpi/jog_tab_target_red.png
+++ b/core/res/res/drawable-land-mdpi/jog_tab_target_red.png
Binary files differ
diff --git a/core/res/res/drawable-land-mdpi/jog_tab_target_yellow.png b/core/res/res/drawable-land-mdpi/jog_tab_target_yellow.png
index efa30ee..111ecdf 100644
--- a/core/res/res/drawable-land-mdpi/jog_tab_target_yellow.png
+++ b/core/res/res/drawable-land-mdpi/jog_tab_target_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-land-xhdpi/btn_lock_normal.9.png b/core/res/res/drawable-land-xhdpi/btn_lock_normal.9.png
index e7c4a19..4347b49 100644
--- a/core/res/res/drawable-land-xhdpi/btn_lock_normal.9.png
+++ b/core/res/res/drawable-land-xhdpi/btn_lock_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/activity_title_bar.9.png b/core/res/res/drawable-ldpi/activity_title_bar.9.png
index 8aaa7d1..f63c678 100644
--- a/core/res/res/drawable-ldpi/activity_title_bar.9.png
+++ b/core/res/res/drawable-ldpi/activity_title_bar.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/arrow_down_float.png b/core/res/res/drawable-ldpi/arrow_down_float.png
index c41340d..e677579 100644
--- a/core/res/res/drawable-ldpi/arrow_down_float.png
+++ b/core/res/res/drawable-ldpi/arrow_down_float.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/arrow_up_float.png b/core/res/res/drawable-ldpi/arrow_up_float.png
index 8b60f12..179b6d8 100644
--- a/core/res/res/drawable-ldpi/arrow_up_float.png
+++ b/core/res/res/drawable-ldpi/arrow_up_float.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/battery_charge_background.png b/core/res/res/drawable-ldpi/battery_charge_background.png
index 503c4f9f..1943722 100644
--- a/core/res/res/drawable-ldpi/battery_charge_background.png
+++ b/core/res/res/drawable-ldpi/battery_charge_background.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/bottom_bar.png b/core/res/res/drawable-ldpi/bottom_bar.png
index c80fd4a..f7fc96e 100644
--- a/core/res/res/drawable-ldpi/bottom_bar.png
+++ b/core/res/res/drawable-ldpi/bottom_bar.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_check_buttonless_off.png b/core/res/res/drawable-ldpi/btn_check_buttonless_off.png
index 327d2c6..2779a22 100644
--- a/core/res/res/drawable-ldpi/btn_check_buttonless_off.png
+++ b/core/res/res/drawable-ldpi/btn_check_buttonless_off.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_check_buttonless_on.png b/core/res/res/drawable-ldpi/btn_check_buttonless_on.png
index 4d0ab2a..b570502 100644
--- a/core/res/res/drawable-ldpi/btn_check_buttonless_on.png
+++ b/core/res/res/drawable-ldpi/btn_check_buttonless_on.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_check_label_background.9.png b/core/res/res/drawable-ldpi/btn_check_label_background.9.png
index 5b08367..2c5588c 100644
--- a/core/res/res/drawable-ldpi/btn_check_label_background.9.png
+++ b/core/res/res/drawable-ldpi/btn_check_label_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_check_off.png b/core/res/res/drawable-ldpi/btn_check_off.png
index f333117..e8d2abe 100644
--- a/core/res/res/drawable-ldpi/btn_check_off.png
+++ b/core/res/res/drawable-ldpi/btn_check_off.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_check_off_disable.png b/core/res/res/drawable-ldpi/btn_check_off_disable.png
index c4d7cd9..8f4ba3e 100644
--- a/core/res/res/drawable-ldpi/btn_check_off_disable.png
+++ b/core/res/res/drawable-ldpi/btn_check_off_disable.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_check_off_disable_focused.png b/core/res/res/drawable-ldpi/btn_check_off_disable_focused.png
index 2bc5899..1bcf979 100644
--- a/core/res/res/drawable-ldpi/btn_check_off_disable_focused.png
+++ b/core/res/res/drawable-ldpi/btn_check_off_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_check_off_pressed.png b/core/res/res/drawable-ldpi/btn_check_off_pressed.png
index fe77b08..412ae71 100644
--- a/core/res/res/drawable-ldpi/btn_check_off_pressed.png
+++ b/core/res/res/drawable-ldpi/btn_check_off_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_check_off_selected.png b/core/res/res/drawable-ldpi/btn_check_off_selected.png
index 58542c4..6de1001 100644
--- a/core/res/res/drawable-ldpi/btn_check_off_selected.png
+++ b/core/res/res/drawable-ldpi/btn_check_off_selected.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_check_on.png b/core/res/res/drawable-ldpi/btn_check_on.png
index f4d777a..37c87ee 100644
--- a/core/res/res/drawable-ldpi/btn_check_on.png
+++ b/core/res/res/drawable-ldpi/btn_check_on.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_check_on_disable.png b/core/res/res/drawable-ldpi/btn_check_on_disable.png
index 57513ca..153d21e 100644
--- a/core/res/res/drawable-ldpi/btn_check_on_disable.png
+++ b/core/res/res/drawable-ldpi/btn_check_on_disable.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_check_on_disable_focused.png b/core/res/res/drawable-ldpi/btn_check_on_disable_focused.png
index 798835e..a15ec6e 100644
--- a/core/res/res/drawable-ldpi/btn_check_on_disable_focused.png
+++ b/core/res/res/drawable-ldpi/btn_check_on_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_check_on_pressed.png b/core/res/res/drawable-ldpi/btn_check_on_pressed.png
index 0f00d17..544513e 100644
--- a/core/res/res/drawable-ldpi/btn_check_on_pressed.png
+++ b/core/res/res/drawable-ldpi/btn_check_on_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_check_on_selected.png b/core/res/res/drawable-ldpi/btn_check_on_selected.png
index 51b3566..04d2654 100644
--- a/core/res/res/drawable-ldpi/btn_check_on_selected.png
+++ b/core/res/res/drawable-ldpi/btn_check_on_selected.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_circle_disable.png b/core/res/res/drawable-ldpi/btn_circle_disable.png
index 87a51c5..20fe800 100644
--- a/core/res/res/drawable-ldpi/btn_circle_disable.png
+++ b/core/res/res/drawable-ldpi/btn_circle_disable.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_circle_disable_focused.png b/core/res/res/drawable-ldpi/btn_circle_disable_focused.png
index cc28e3b..405b135 100644
--- a/core/res/res/drawable-ldpi/btn_circle_disable_focused.png
+++ b/core/res/res/drawable-ldpi/btn_circle_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_circle_normal.png b/core/res/res/drawable-ldpi/btn_circle_normal.png
index b25ad81..387e6af 100644
--- a/core/res/res/drawable-ldpi/btn_circle_normal.png
+++ b/core/res/res/drawable-ldpi/btn_circle_normal.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_circle_pressed.png b/core/res/res/drawable-ldpi/btn_circle_pressed.png
index abeedad..b81eaf8 100644
--- a/core/res/res/drawable-ldpi/btn_circle_pressed.png
+++ b/core/res/res/drawable-ldpi/btn_circle_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_circle_selected.png b/core/res/res/drawable-ldpi/btn_circle_selected.png
index e3e8d13..b633bd2 100644
--- a/core/res/res/drawable-ldpi/btn_circle_selected.png
+++ b/core/res/res/drawable-ldpi/btn_circle_selected.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_close_normal.png b/core/res/res/drawable-ldpi/btn_close_normal.png
index e4de088..9d43318 100644
--- a/core/res/res/drawable-ldpi/btn_close_normal.png
+++ b/core/res/res/drawable-ldpi/btn_close_normal.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_close_pressed.png b/core/res/res/drawable-ldpi/btn_close_pressed.png
index 5d946bd..e87376e 100644
--- a/core/res/res/drawable-ldpi/btn_close_pressed.png
+++ b/core/res/res/drawable-ldpi/btn_close_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_close_selected.png b/core/res/res/drawable-ldpi/btn_close_selected.png
index c1ee5a8..b3432bd 100644
--- a/core/res/res/drawable-ldpi/btn_close_selected.png
+++ b/core/res/res/drawable-ldpi/btn_close_selected.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_default_normal.9.png b/core/res/res/drawable-ldpi/btn_default_normal.9.png
index 198da17..1a5fab5 100644
--- a/core/res/res/drawable-ldpi/btn_default_normal.9.png
+++ b/core/res/res/drawable-ldpi/btn_default_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_default_normal_disable.9.png b/core/res/res/drawable-ldpi/btn_default_normal_disable.9.png
index 2e61b50..8b8d6e4 100644
--- a/core/res/res/drawable-ldpi/btn_default_normal_disable.9.png
+++ b/core/res/res/drawable-ldpi/btn_default_normal_disable.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_default_normal_disable_focused.9.png b/core/res/res/drawable-ldpi/btn_default_normal_disable_focused.9.png
index 9fab12e..500e498 100644
--- a/core/res/res/drawable-ldpi/btn_default_normal_disable_focused.9.png
+++ b/core/res/res/drawable-ldpi/btn_default_normal_disable_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_default_pressed.9.png b/core/res/res/drawable-ldpi/btn_default_pressed.9.png
index f5a21b2..1b13a5b 100644
--- a/core/res/res/drawable-ldpi/btn_default_pressed.9.png
+++ b/core/res/res/drawable-ldpi/btn_default_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_default_selected.9.png b/core/res/res/drawable-ldpi/btn_default_selected.9.png
index a09da00..9f8374e 100644
--- a/core/res/res/drawable-ldpi/btn_default_selected.9.png
+++ b/core/res/res/drawable-ldpi/btn_default_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_default_small_normal.9.png b/core/res/res/drawable-ldpi/btn_default_small_normal.9.png
index 4e69058..b72a02e 100644
--- a/core/res/res/drawable-ldpi/btn_default_small_normal.9.png
+++ b/core/res/res/drawable-ldpi/btn_default_small_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_default_small_normal_disable.9.png b/core/res/res/drawable-ldpi/btn_default_small_normal_disable.9.png
index 64fce65..dc1e97c 100644
--- a/core/res/res/drawable-ldpi/btn_default_small_normal_disable.9.png
+++ b/core/res/res/drawable-ldpi/btn_default_small_normal_disable.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_default_small_normal_disable_focused.9.png b/core/res/res/drawable-ldpi/btn_default_small_normal_disable_focused.9.png
index 528b5e1..ca2b7ef 100644
--- a/core/res/res/drawable-ldpi/btn_default_small_normal_disable_focused.9.png
+++ b/core/res/res/drawable-ldpi/btn_default_small_normal_disable_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_default_small_pressed.9.png b/core/res/res/drawable-ldpi/btn_default_small_pressed.9.png
index bf70128..ed007e2 100644
--- a/core/res/res/drawable-ldpi/btn_default_small_pressed.9.png
+++ b/core/res/res/drawable-ldpi/btn_default_small_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_default_small_selected.9.png b/core/res/res/drawable-ldpi/btn_default_small_selected.9.png
index 71938d0..57f3982 100644
--- a/core/res/res/drawable-ldpi/btn_default_small_selected.9.png
+++ b/core/res/res/drawable-ldpi/btn_default_small_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_default_transparent_normal.9.png b/core/res/res/drawable-ldpi/btn_default_transparent_normal.9.png
index 2c7249e..00acba6 100644
--- a/core/res/res/drawable-ldpi/btn_default_transparent_normal.9.png
+++ b/core/res/res/drawable-ldpi/btn_default_transparent_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_dialog_disable.png b/core/res/res/drawable-ldpi/btn_dialog_disable.png
index 82d13f2..bd5759f 100644
--- a/core/res/res/drawable-ldpi/btn_dialog_disable.png
+++ b/core/res/res/drawable-ldpi/btn_dialog_disable.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_dialog_normal.png b/core/res/res/drawable-ldpi/btn_dialog_normal.png
index e4de088..9d43318 100644
--- a/core/res/res/drawable-ldpi/btn_dialog_normal.png
+++ b/core/res/res/drawable-ldpi/btn_dialog_normal.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_dialog_pressed.png b/core/res/res/drawable-ldpi/btn_dialog_pressed.png
index 557c13a..0c19b40 100644
--- a/core/res/res/drawable-ldpi/btn_dialog_pressed.png
+++ b/core/res/res/drawable-ldpi/btn_dialog_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_dialog_selected.png b/core/res/res/drawable-ldpi/btn_dialog_selected.png
index f63ce27..f17b96d 100644
--- a/core/res/res/drawable-ldpi/btn_dialog_selected.png
+++ b/core/res/res/drawable-ldpi/btn_dialog_selected.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_dropdown_disabled.9.png b/core/res/res/drawable-ldpi/btn_dropdown_disabled.9.png
index 27cb8f5..e986bba 100644
--- a/core/res/res/drawable-ldpi/btn_dropdown_disabled.9.png
+++ b/core/res/res/drawable-ldpi/btn_dropdown_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_dropdown_disabled_focused.9.png b/core/res/res/drawable-ldpi/btn_dropdown_disabled_focused.9.png
index a0231c5..2d1ff44 100644
--- a/core/res/res/drawable-ldpi/btn_dropdown_disabled_focused.9.png
+++ b/core/res/res/drawable-ldpi/btn_dropdown_disabled_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_dropdown_normal.9.png b/core/res/res/drawable-ldpi/btn_dropdown_normal.9.png
index b23e10ffa..575a8a3 100644
--- a/core/res/res/drawable-ldpi/btn_dropdown_normal.9.png
+++ b/core/res/res/drawable-ldpi/btn_dropdown_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_dropdown_pressed.9.png b/core/res/res/drawable-ldpi/btn_dropdown_pressed.9.png
index c3c08e4..fc094f5 100644
--- a/core/res/res/drawable-ldpi/btn_dropdown_pressed.9.png
+++ b/core/res/res/drawable-ldpi/btn_dropdown_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_dropdown_selected.9.png b/core/res/res/drawable-ldpi/btn_dropdown_selected.9.png
index 2660e43..5bccda7 100644
--- a/core/res/res/drawable-ldpi/btn_dropdown_selected.9.png
+++ b/core/res/res/drawable-ldpi/btn_dropdown_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_erase_default.9.png b/core/res/res/drawable-ldpi/btn_erase_default.9.png
index dc592ca..ecc11ce 100644
--- a/core/res/res/drawable-ldpi/btn_erase_default.9.png
+++ b/core/res/res/drawable-ldpi/btn_erase_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_erase_pressed.9.png b/core/res/res/drawable-ldpi/btn_erase_pressed.9.png
index 48c0570..ca11dd4 100644
--- a/core/res/res/drawable-ldpi/btn_erase_pressed.9.png
+++ b/core/res/res/drawable-ldpi/btn_erase_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_erase_selected.9.png b/core/res/res/drawable-ldpi/btn_erase_selected.9.png
index 51f7b86..b4ffee0 100644
--- a/core/res/res/drawable-ldpi/btn_erase_selected.9.png
+++ b/core/res/res/drawable-ldpi/btn_erase_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_global_search_normal.9.png b/core/res/res/drawable-ldpi/btn_global_search_normal.9.png
index 60bd3ce..bb28e17 100644
--- a/core/res/res/drawable-ldpi/btn_global_search_normal.9.png
+++ b/core/res/res/drawable-ldpi/btn_global_search_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_keyboard_key_fulltrans_normal.9.png b/core/res/res/drawable-ldpi/btn_keyboard_key_fulltrans_normal.9.png
index 8cf50b8..cc56972 100644
--- a/core/res/res/drawable-ldpi/btn_keyboard_key_fulltrans_normal.9.png
+++ b/core/res/res/drawable-ldpi/btn_keyboard_key_fulltrans_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_keyboard_key_fulltrans_normal_off.9.png b/core/res/res/drawable-ldpi/btn_keyboard_key_fulltrans_normal_off.9.png
index d853bf1..4b9219a 100644
--- a/core/res/res/drawable-ldpi/btn_keyboard_key_fulltrans_normal_off.9.png
+++ b/core/res/res/drawable-ldpi/btn_keyboard_key_fulltrans_normal_off.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_keyboard_key_fulltrans_normal_on.9.png b/core/res/res/drawable-ldpi/btn_keyboard_key_fulltrans_normal_on.9.png
index f54e948..14ad3f6 100644
--- a/core/res/res/drawable-ldpi/btn_keyboard_key_fulltrans_normal_on.9.png
+++ b/core/res/res/drawable-ldpi/btn_keyboard_key_fulltrans_normal_on.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_keyboard_key_fulltrans_pressed.9.png b/core/res/res/drawable-ldpi/btn_keyboard_key_fulltrans_pressed.9.png
index ad7c951..317c2ae 100644
--- a/core/res/res/drawable-ldpi/btn_keyboard_key_fulltrans_pressed.9.png
+++ b/core/res/res/drawable-ldpi/btn_keyboard_key_fulltrans_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_keyboard_key_fulltrans_pressed_off.9.png b/core/res/res/drawable-ldpi/btn_keyboard_key_fulltrans_pressed_off.9.png
index 1a075d29..1851143 100644
--- a/core/res/res/drawable-ldpi/btn_keyboard_key_fulltrans_pressed_off.9.png
+++ b/core/res/res/drawable-ldpi/btn_keyboard_key_fulltrans_pressed_off.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_keyboard_key_fulltrans_pressed_on.9.png b/core/res/res/drawable-ldpi/btn_keyboard_key_fulltrans_pressed_on.9.png
index 5933f61..b5ede76 100644
--- a/core/res/res/drawable-ldpi/btn_keyboard_key_fulltrans_pressed_on.9.png
+++ b/core/res/res/drawable-ldpi/btn_keyboard_key_fulltrans_pressed_on.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_keyboard_key_normal.9.png b/core/res/res/drawable-ldpi/btn_keyboard_key_normal.9.png
index 69db65f..b9147c6 100644
--- a/core/res/res/drawable-ldpi/btn_keyboard_key_normal.9.png
+++ b/core/res/res/drawable-ldpi/btn_keyboard_key_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_keyboard_key_normal_off.9.png b/core/res/res/drawable-ldpi/btn_keyboard_key_normal_off.9.png
index 37c5fed..15a98be 100644
--- a/core/res/res/drawable-ldpi/btn_keyboard_key_normal_off.9.png
+++ b/core/res/res/drawable-ldpi/btn_keyboard_key_normal_off.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_keyboard_key_normal_on.9.png b/core/res/res/drawable-ldpi/btn_keyboard_key_normal_on.9.png
index 019e6f7..5a45ccf6 100644
--- a/core/res/res/drawable-ldpi/btn_keyboard_key_normal_on.9.png
+++ b/core/res/res/drawable-ldpi/btn_keyboard_key_normal_on.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_keyboard_key_pressed.9.png b/core/res/res/drawable-ldpi/btn_keyboard_key_pressed.9.png
index d3827f0..6f67af5 100644
--- a/core/res/res/drawable-ldpi/btn_keyboard_key_pressed.9.png
+++ b/core/res/res/drawable-ldpi/btn_keyboard_key_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_keyboard_key_pressed_off.9.png b/core/res/res/drawable-ldpi/btn_keyboard_key_pressed_off.9.png
index 2bef004..6997c30 100644
--- a/core/res/res/drawable-ldpi/btn_keyboard_key_pressed_off.9.png
+++ b/core/res/res/drawable-ldpi/btn_keyboard_key_pressed_off.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_keyboard_key_pressed_on.9.png b/core/res/res/drawable-ldpi/btn_keyboard_key_pressed_on.9.png
index 25daabe..5fcf63f 100644
--- a/core/res/res/drawable-ldpi/btn_keyboard_key_pressed_on.9.png
+++ b/core/res/res/drawable-ldpi/btn_keyboard_key_pressed_on.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_keyboard_key_trans_normal.9.png b/core/res/res/drawable-ldpi/btn_keyboard_key_trans_normal.9.png
index 9d026c4..5ce685d 100644
--- a/core/res/res/drawable-ldpi/btn_keyboard_key_trans_normal.9.png
+++ b/core/res/res/drawable-ldpi/btn_keyboard_key_trans_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_keyboard_key_trans_normal_off.9.png b/core/res/res/drawable-ldpi/btn_keyboard_key_trans_normal_off.9.png
index 6ededbe..8e943b7 100644
--- a/core/res/res/drawable-ldpi/btn_keyboard_key_trans_normal_off.9.png
+++ b/core/res/res/drawable-ldpi/btn_keyboard_key_trans_normal_off.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_keyboard_key_trans_normal_on.9.png b/core/res/res/drawable-ldpi/btn_keyboard_key_trans_normal_on.9.png
index 987014f..33dac80 100644
--- a/core/res/res/drawable-ldpi/btn_keyboard_key_trans_normal_on.9.png
+++ b/core/res/res/drawable-ldpi/btn_keyboard_key_trans_normal_on.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_keyboard_key_trans_pressed.9.png b/core/res/res/drawable-ldpi/btn_keyboard_key_trans_pressed.9.png
index d19a0fcc..d86542b 100644
--- a/core/res/res/drawable-ldpi/btn_keyboard_key_trans_pressed.9.png
+++ b/core/res/res/drawable-ldpi/btn_keyboard_key_trans_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_keyboard_key_trans_pressed_off.9.png b/core/res/res/drawable-ldpi/btn_keyboard_key_trans_pressed_off.9.png
index 978ff4c..c9b1786 100644
--- a/core/res/res/drawable-ldpi/btn_keyboard_key_trans_pressed_off.9.png
+++ b/core/res/res/drawable-ldpi/btn_keyboard_key_trans_pressed_off.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_keyboard_key_trans_pressed_on.9.png b/core/res/res/drawable-ldpi/btn_keyboard_key_trans_pressed_on.9.png
index 8355c7d..969501b 100644
--- a/core/res/res/drawable-ldpi/btn_keyboard_key_trans_pressed_on.9.png
+++ b/core/res/res/drawable-ldpi/btn_keyboard_key_trans_pressed_on.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_keyboard_key_trans_selected.9.png b/core/res/res/drawable-ldpi/btn_keyboard_key_trans_selected.9.png
index 8afb908..9aee646 100644
--- a/core/res/res/drawable-ldpi/btn_keyboard_key_trans_selected.9.png
+++ b/core/res/res/drawable-ldpi/btn_keyboard_key_trans_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_media_player.9.png b/core/res/res/drawable-ldpi/btn_media_player.9.png
index 7096dbc..c59261b 100644
--- a/core/res/res/drawable-ldpi/btn_media_player.9.png
+++ b/core/res/res/drawable-ldpi/btn_media_player.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_media_player_disabled.9.png b/core/res/res/drawable-ldpi/btn_media_player_disabled.9.png
index 83b1059..5ff9c27 100644
--- a/core/res/res/drawable-ldpi/btn_media_player_disabled.9.png
+++ b/core/res/res/drawable-ldpi/btn_media_player_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_media_player_disabled_selected.9.png b/core/res/res/drawable-ldpi/btn_media_player_disabled_selected.9.png
index f55ac21..13f142d 100644
--- a/core/res/res/drawable-ldpi/btn_media_player_disabled_selected.9.png
+++ b/core/res/res/drawable-ldpi/btn_media_player_disabled_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_media_player_pressed.9.png b/core/res/res/drawable-ldpi/btn_media_player_pressed.9.png
index de58ee2..46cd393 100644
--- a/core/res/res/drawable-ldpi/btn_media_player_pressed.9.png
+++ b/core/res/res/drawable-ldpi/btn_media_player_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_media_player_selected.9.png b/core/res/res/drawable-ldpi/btn_media_player_selected.9.png
index 5443580..851279e 100644
--- a/core/res/res/drawable-ldpi/btn_media_player_selected.9.png
+++ b/core/res/res/drawable-ldpi/btn_media_player_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_minus_default.png b/core/res/res/drawable-ldpi/btn_minus_default.png
index 19c66e0..df55e35 100644
--- a/core/res/res/drawable-ldpi/btn_minus_default.png
+++ b/core/res/res/drawable-ldpi/btn_minus_default.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_minus_disable.png b/core/res/res/drawable-ldpi/btn_minus_disable.png
index 7b91ea6..fd11ebe 100644
--- a/core/res/res/drawable-ldpi/btn_minus_disable.png
+++ b/core/res/res/drawable-ldpi/btn_minus_disable.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_minus_disable_focused.png b/core/res/res/drawable-ldpi/btn_minus_disable_focused.png
index a347e34..2815cb7 100644
--- a/core/res/res/drawable-ldpi/btn_minus_disable_focused.png
+++ b/core/res/res/drawable-ldpi/btn_minus_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_minus_pressed.png b/core/res/res/drawable-ldpi/btn_minus_pressed.png
index aaa9746..801186b 100644
--- a/core/res/res/drawable-ldpi/btn_minus_pressed.png
+++ b/core/res/res/drawable-ldpi/btn_minus_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_minus_selected.png b/core/res/res/drawable-ldpi/btn_minus_selected.png
index 29c6962..4e5efb9 100644
--- a/core/res/res/drawable-ldpi/btn_minus_selected.png
+++ b/core/res/res/drawable-ldpi/btn_minus_selected.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_plus_default.png b/core/res/res/drawable-ldpi/btn_plus_default.png
index 8a5c600..58557d7 100644
--- a/core/res/res/drawable-ldpi/btn_plus_default.png
+++ b/core/res/res/drawable-ldpi/btn_plus_default.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_plus_disable.png b/core/res/res/drawable-ldpi/btn_plus_disable.png
index 1903ffa..b5a9c9a 100644
--- a/core/res/res/drawable-ldpi/btn_plus_disable.png
+++ b/core/res/res/drawable-ldpi/btn_plus_disable.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_plus_disable_focused.png b/core/res/res/drawable-ldpi/btn_plus_disable_focused.png
index 92f228a..404a4f5 100644
--- a/core/res/res/drawable-ldpi/btn_plus_disable_focused.png
+++ b/core/res/res/drawable-ldpi/btn_plus_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_plus_pressed.png b/core/res/res/drawable-ldpi/btn_plus_pressed.png
index 28f4e02..51f812f 100644
--- a/core/res/res/drawable-ldpi/btn_plus_pressed.png
+++ b/core/res/res/drawable-ldpi/btn_plus_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_plus_selected.png b/core/res/res/drawable-ldpi/btn_plus_selected.png
index c6fab19..3e39e9a 100644
--- a/core/res/res/drawable-ldpi/btn_plus_selected.png
+++ b/core/res/res/drawable-ldpi/btn_plus_selected.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_radio_label_background.9.png b/core/res/res/drawable-ldpi/btn_radio_label_background.9.png
index d04c41f..553e784 100644
--- a/core/res/res/drawable-ldpi/btn_radio_label_background.9.png
+++ b/core/res/res/drawable-ldpi/btn_radio_label_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_radio_off.png b/core/res/res/drawable-ldpi/btn_radio_off.png
index 6df3b0d..f3d67a0 100644
--- a/core/res/res/drawable-ldpi/btn_radio_off.png
+++ b/core/res/res/drawable-ldpi/btn_radio_off.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_radio_off_pressed.png b/core/res/res/drawable-ldpi/btn_radio_off_pressed.png
index 4848ff0..2c7d136 100644
--- a/core/res/res/drawable-ldpi/btn_radio_off_pressed.png
+++ b/core/res/res/drawable-ldpi/btn_radio_off_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_radio_off_selected.png b/core/res/res/drawable-ldpi/btn_radio_off_selected.png
index 9336722..82b2d51 100644
--- a/core/res/res/drawable-ldpi/btn_radio_off_selected.png
+++ b/core/res/res/drawable-ldpi/btn_radio_off_selected.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_radio_on.png b/core/res/res/drawable-ldpi/btn_radio_on.png
index 65e5791..1a87303 100644
--- a/core/res/res/drawable-ldpi/btn_radio_on.png
+++ b/core/res/res/drawable-ldpi/btn_radio_on.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_radio_on_pressed.png b/core/res/res/drawable-ldpi/btn_radio_on_pressed.png
index 4856c32..787c5f1 100644
--- a/core/res/res/drawable-ldpi/btn_radio_on_pressed.png
+++ b/core/res/res/drawable-ldpi/btn_radio_on_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_radio_on_selected.png b/core/res/res/drawable-ldpi/btn_radio_on_selected.png
index 8b19dc7..064774a 100644
--- a/core/res/res/drawable-ldpi/btn_radio_on_selected.png
+++ b/core/res/res/drawable-ldpi/btn_radio_on_selected.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_rating_star_off_normal.png b/core/res/res/drawable-ldpi/btn_rating_star_off_normal.png
index 5967bd3..f8263db 100644
--- a/core/res/res/drawable-ldpi/btn_rating_star_off_normal.png
+++ b/core/res/res/drawable-ldpi/btn_rating_star_off_normal.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_rating_star_off_pressed.png b/core/res/res/drawable-ldpi/btn_rating_star_off_pressed.png
index 209e6a4..d987706 100644
--- a/core/res/res/drawable-ldpi/btn_rating_star_off_pressed.png
+++ b/core/res/res/drawable-ldpi/btn_rating_star_off_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_rating_star_off_selected.png b/core/res/res/drawable-ldpi/btn_rating_star_off_selected.png
index c095f7f..0081804 100644
--- a/core/res/res/drawable-ldpi/btn_rating_star_off_selected.png
+++ b/core/res/res/drawable-ldpi/btn_rating_star_off_selected.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_rating_star_on_normal.png b/core/res/res/drawable-ldpi/btn_rating_star_on_normal.png
index 89d26129..d99456d 100644
--- a/core/res/res/drawable-ldpi/btn_rating_star_on_normal.png
+++ b/core/res/res/drawable-ldpi/btn_rating_star_on_normal.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_rating_star_on_pressed.png b/core/res/res/drawable-ldpi/btn_rating_star_on_pressed.png
index 6386eaa..6fe13b1 100644
--- a/core/res/res/drawable-ldpi/btn_rating_star_on_pressed.png
+++ b/core/res/res/drawable-ldpi/btn_rating_star_on_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_rating_star_on_selected.png b/core/res/res/drawable-ldpi/btn_rating_star_on_selected.png
index e1edf4e..03368d6 100644
--- a/core/res/res/drawable-ldpi/btn_rating_star_on_selected.png
+++ b/core/res/res/drawable-ldpi/btn_rating_star_on_selected.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_search_dialog_default.9.png b/core/res/res/drawable-ldpi/btn_search_dialog_default.9.png
index 35111b7..463aeee 100644
--- a/core/res/res/drawable-ldpi/btn_search_dialog_default.9.png
+++ b/core/res/res/drawable-ldpi/btn_search_dialog_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_search_dialog_pressed.9.png b/core/res/res/drawable-ldpi/btn_search_dialog_pressed.9.png
index 8ca4c65..1d1f952 100644
--- a/core/res/res/drawable-ldpi/btn_search_dialog_pressed.9.png
+++ b/core/res/res/drawable-ldpi/btn_search_dialog_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_search_dialog_selected.9.png b/core/res/res/drawable-ldpi/btn_search_dialog_selected.9.png
index 0bee0b7..cae6502 100644
--- a/core/res/res/drawable-ldpi/btn_search_dialog_selected.9.png
+++ b/core/res/res/drawable-ldpi/btn_search_dialog_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_search_dialog_voice_default.9.png b/core/res/res/drawable-ldpi/btn_search_dialog_voice_default.9.png
index f9e7298..2f12bda 100644
--- a/core/res/res/drawable-ldpi/btn_search_dialog_voice_default.9.png
+++ b/core/res/res/drawable-ldpi/btn_search_dialog_voice_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_search_dialog_voice_pressed.9.png b/core/res/res/drawable-ldpi/btn_search_dialog_voice_pressed.9.png
index a130f65..ec188296 100644
--- a/core/res/res/drawable-ldpi/btn_search_dialog_voice_pressed.9.png
+++ b/core/res/res/drawable-ldpi/btn_search_dialog_voice_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_search_dialog_voice_selected.9.png b/core/res/res/drawable-ldpi/btn_search_dialog_voice_selected.9.png
index c055bfe..8dfd641 100644
--- a/core/res/res/drawable-ldpi/btn_search_dialog_voice_selected.9.png
+++ b/core/res/res/drawable-ldpi/btn_search_dialog_voice_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_square_overlay_disabled.png b/core/res/res/drawable-ldpi/btn_square_overlay_disabled.png
index 3b60946..e61ea44 100644
--- a/core/res/res/drawable-ldpi/btn_square_overlay_disabled.png
+++ b/core/res/res/drawable-ldpi/btn_square_overlay_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_square_overlay_disabled_focused.png b/core/res/res/drawable-ldpi/btn_square_overlay_disabled_focused.png
index a36a9dd..30a296b 100644
--- a/core/res/res/drawable-ldpi/btn_square_overlay_disabled_focused.png
+++ b/core/res/res/drawable-ldpi/btn_square_overlay_disabled_focused.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_square_overlay_normal.png b/core/res/res/drawable-ldpi/btn_square_overlay_normal.png
index 4537623..66e94a6 100644
--- a/core/res/res/drawable-ldpi/btn_square_overlay_normal.png
+++ b/core/res/res/drawable-ldpi/btn_square_overlay_normal.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_square_overlay_pressed.png b/core/res/res/drawable-ldpi/btn_square_overlay_pressed.png
index 62f2246..c2cc3bd 100644
--- a/core/res/res/drawable-ldpi/btn_square_overlay_pressed.png
+++ b/core/res/res/drawable-ldpi/btn_square_overlay_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_square_overlay_selected.png b/core/res/res/drawable-ldpi/btn_square_overlay_selected.png
index 264d3fa..5a73610 100644
--- a/core/res/res/drawable-ldpi/btn_square_overlay_selected.png
+++ b/core/res/res/drawable-ldpi/btn_square_overlay_selected.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_star_big_off.png b/core/res/res/drawable-ldpi/btn_star_big_off.png
index f0f1eb8..b695b2d 100644
--- a/core/res/res/drawable-ldpi/btn_star_big_off.png
+++ b/core/res/res/drawable-ldpi/btn_star_big_off.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_star_big_off_disable.png b/core/res/res/drawable-ldpi/btn_star_big_off_disable.png
index c6f2e20..18251f2 100644
--- a/core/res/res/drawable-ldpi/btn_star_big_off_disable.png
+++ b/core/res/res/drawable-ldpi/btn_star_big_off_disable.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_star_big_off_disable_focused.png b/core/res/res/drawable-ldpi/btn_star_big_off_disable_focused.png
index 228a84e..94a8ebe 100644
--- a/core/res/res/drawable-ldpi/btn_star_big_off_disable_focused.png
+++ b/core/res/res/drawable-ldpi/btn_star_big_off_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_star_big_off_pressed.png b/core/res/res/drawable-ldpi/btn_star_big_off_pressed.png
index 041f81a..55f3f61 100644
--- a/core/res/res/drawable-ldpi/btn_star_big_off_pressed.png
+++ b/core/res/res/drawable-ldpi/btn_star_big_off_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_star_big_off_selected.png b/core/res/res/drawable-ldpi/btn_star_big_off_selected.png
index adc8151..2a4464c 100644
--- a/core/res/res/drawable-ldpi/btn_star_big_off_selected.png
+++ b/core/res/res/drawable-ldpi/btn_star_big_off_selected.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_star_big_on.png b/core/res/res/drawable-ldpi/btn_star_big_on.png
index cf5ed35..44a4b83 100644
--- a/core/res/res/drawable-ldpi/btn_star_big_on.png
+++ b/core/res/res/drawable-ldpi/btn_star_big_on.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_star_big_on_disable.png b/core/res/res/drawable-ldpi/btn_star_big_on_disable.png
index 53e6c65..b697b6a 100644
--- a/core/res/res/drawable-ldpi/btn_star_big_on_disable.png
+++ b/core/res/res/drawable-ldpi/btn_star_big_on_disable.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_star_big_on_disable_focused.png b/core/res/res/drawable-ldpi/btn_star_big_on_disable_focused.png
index 8535013..552575f 100644
--- a/core/res/res/drawable-ldpi/btn_star_big_on_disable_focused.png
+++ b/core/res/res/drawable-ldpi/btn_star_big_on_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_star_big_on_pressed.png b/core/res/res/drawable-ldpi/btn_star_big_on_pressed.png
index 272787f..474a31d 100644
--- a/core/res/res/drawable-ldpi/btn_star_big_on_pressed.png
+++ b/core/res/res/drawable-ldpi/btn_star_big_on_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_star_big_on_selected.png b/core/res/res/drawable-ldpi/btn_star_big_on_selected.png
index 938d743..c60ba76 100644
--- a/core/res/res/drawable-ldpi/btn_star_big_on_selected.png
+++ b/core/res/res/drawable-ldpi/btn_star_big_on_selected.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_star_label_background.9.png b/core/res/res/drawable-ldpi/btn_star_label_background.9.png
index 3bc13c8..dd39991 100644
--- a/core/res/res/drawable-ldpi/btn_star_label_background.9.png
+++ b/core/res/res/drawable-ldpi/btn_star_label_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_toggle_off.9.png b/core/res/res/drawable-ldpi/btn_toggle_off.9.png
index d0245ff..9ef6e9e 100644
--- a/core/res/res/drawable-ldpi/btn_toggle_off.9.png
+++ b/core/res/res/drawable-ldpi/btn_toggle_off.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_toggle_on.9.png b/core/res/res/drawable-ldpi/btn_toggle_on.9.png
index 0987759..825cf54 100644
--- a/core/res/res/drawable-ldpi/btn_toggle_on.9.png
+++ b/core/res/res/drawable-ldpi/btn_toggle_on.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_zoom_down_disabled.9.png b/core/res/res/drawable-ldpi/btn_zoom_down_disabled.9.png
index 0346abc..c5ef621 100644
--- a/core/res/res/drawable-ldpi/btn_zoom_down_disabled.9.png
+++ b/core/res/res/drawable-ldpi/btn_zoom_down_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_zoom_down_disabled_focused.9.png b/core/res/res/drawable-ldpi/btn_zoom_down_disabled_focused.9.png
index b03aa1b..57bfb16 100644
--- a/core/res/res/drawable-ldpi/btn_zoom_down_disabled_focused.9.png
+++ b/core/res/res/drawable-ldpi/btn_zoom_down_disabled_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_zoom_down_normal.9.png b/core/res/res/drawable-ldpi/btn_zoom_down_normal.9.png
index aa2464c..e8d656e 100644
--- a/core/res/res/drawable-ldpi/btn_zoom_down_normal.9.png
+++ b/core/res/res/drawable-ldpi/btn_zoom_down_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_zoom_down_pressed.9.png b/core/res/res/drawable-ldpi/btn_zoom_down_pressed.9.png
index caa4d30..ebc71b0 100644
--- a/core/res/res/drawable-ldpi/btn_zoom_down_pressed.9.png
+++ b/core/res/res/drawable-ldpi/btn_zoom_down_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_zoom_down_selected.9.png b/core/res/res/drawable-ldpi/btn_zoom_down_selected.9.png
index b814785..af985f9 100644
--- a/core/res/res/drawable-ldpi/btn_zoom_down_selected.9.png
+++ b/core/res/res/drawable-ldpi/btn_zoom_down_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_zoom_page_normal.png b/core/res/res/drawable-ldpi/btn_zoom_page_normal.png
index 453bf40..2cdc457 100644
--- a/core/res/res/drawable-ldpi/btn_zoom_page_normal.png
+++ b/core/res/res/drawable-ldpi/btn_zoom_page_normal.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_zoom_page_press.png b/core/res/res/drawable-ldpi/btn_zoom_page_press.png
index 82c29c8..5373ddf 100644
--- a/core/res/res/drawable-ldpi/btn_zoom_page_press.png
+++ b/core/res/res/drawable-ldpi/btn_zoom_page_press.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_zoom_up_disabled.9.png b/core/res/res/drawable-ldpi/btn_zoom_up_disabled.9.png
index e64f178..ba86c97 100644
--- a/core/res/res/drawable-ldpi/btn_zoom_up_disabled.9.png
+++ b/core/res/res/drawable-ldpi/btn_zoom_up_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_zoom_up_disabled_focused.9.png b/core/res/res/drawable-ldpi/btn_zoom_up_disabled_focused.9.png
index 3b21d0a..5dd86df 100644
--- a/core/res/res/drawable-ldpi/btn_zoom_up_disabled_focused.9.png
+++ b/core/res/res/drawable-ldpi/btn_zoom_up_disabled_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_zoom_up_normal.9.png b/core/res/res/drawable-ldpi/btn_zoom_up_normal.9.png
index f4b56d5..99f682d 100644
--- a/core/res/res/drawable-ldpi/btn_zoom_up_normal.9.png
+++ b/core/res/res/drawable-ldpi/btn_zoom_up_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_zoom_up_pressed.9.png b/core/res/res/drawable-ldpi/btn_zoom_up_pressed.9.png
index 45c668c..2b8849c 100644
--- a/core/res/res/drawable-ldpi/btn_zoom_up_pressed.9.png
+++ b/core/res/res/drawable-ldpi/btn_zoom_up_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_zoom_up_selected.9.png b/core/res/res/drawable-ldpi/btn_zoom_up_selected.9.png
index 1a07a52..b02abc9 100644
--- a/core/res/res/drawable-ldpi/btn_zoom_up_selected.9.png
+++ b/core/res/res/drawable-ldpi/btn_zoom_up_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/button_onoff_indicator_off.png b/core/res/res/drawable-ldpi/button_onoff_indicator_off.png
index 7946356..3b31524 100644
--- a/core/res/res/drawable-ldpi/button_onoff_indicator_off.png
+++ b/core/res/res/drawable-ldpi/button_onoff_indicator_off.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/button_onoff_indicator_on.png b/core/res/res/drawable-ldpi/button_onoff_indicator_on.png
index 6b817d5..f77bd87 100644
--- a/core/res/res/drawable-ldpi/button_onoff_indicator_on.png
+++ b/core/res/res/drawable-ldpi/button_onoff_indicator_on.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/call_contact.png b/core/res/res/drawable-ldpi/call_contact.png
index bee1d20..971b94c 100644
--- a/core/res/res/drawable-ldpi/call_contact.png
+++ b/core/res/res/drawable-ldpi/call_contact.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/checkbox_off_background.png b/core/res/res/drawable-ldpi/checkbox_off_background.png
index ab77983..6979a1b 100644
--- a/core/res/res/drawable-ldpi/checkbox_off_background.png
+++ b/core/res/res/drawable-ldpi/checkbox_off_background.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/checkbox_on_background.png b/core/res/res/drawable-ldpi/checkbox_on_background.png
index dd92a4c..942a41f 100644
--- a/core/res/res/drawable-ldpi/checkbox_on_background.png
+++ b/core/res/res/drawable-ldpi/checkbox_on_background.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/code_lock_bottom.9.png b/core/res/res/drawable-ldpi/code_lock_bottom.9.png
index dddac51..2457b6a 100644
--- a/core/res/res/drawable-ldpi/code_lock_bottom.9.png
+++ b/core/res/res/drawable-ldpi/code_lock_bottom.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/code_lock_left.9.png b/core/res/res/drawable-ldpi/code_lock_left.9.png
index 8834f74..bd66ab7 100644
--- a/core/res/res/drawable-ldpi/code_lock_left.9.png
+++ b/core/res/res/drawable-ldpi/code_lock_left.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/code_lock_top.9.png b/core/res/res/drawable-ldpi/code_lock_top.9.png
index 2a5e353..7679f4d 100644
--- a/core/res/res/drawable-ldpi/code_lock_top.9.png
+++ b/core/res/res/drawable-ldpi/code_lock_top.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/compass_arrow.png b/core/res/res/drawable-ldpi/compass_arrow.png
index f59015c..6498af0 100644
--- a/core/res/res/drawable-ldpi/compass_arrow.png
+++ b/core/res/res/drawable-ldpi/compass_arrow.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/compass_base.png b/core/res/res/drawable-ldpi/compass_base.png
index a2eeb07..11d971b 100644
--- a/core/res/res/drawable-ldpi/compass_base.png
+++ b/core/res/res/drawable-ldpi/compass_base.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/contact_header_bg.9.png b/core/res/res/drawable-ldpi/contact_header_bg.9.png
index 20f0cd3..4121296 100644
--- a/core/res/res/drawable-ldpi/contact_header_bg.9.png
+++ b/core/res/res/drawable-ldpi/contact_header_bg.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/create_contact.png b/core/res/res/drawable-ldpi/create_contact.png
index c920ef4..94a7a74 100644
--- a/core/res/res/drawable-ldpi/create_contact.png
+++ b/core/res/res/drawable-ldpi/create_contact.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/dark_header.9.png b/core/res/res/drawable-ldpi/dark_header.9.png
index 88fa160..1f304918 100644
--- a/core/res/res/drawable-ldpi/dark_header.9.png
+++ b/core/res/res/drawable-ldpi/dark_header.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/dialog_divider_horizontal_light.9.png b/core/res/res/drawable-ldpi/dialog_divider_horizontal_light.9.png
index 75a1534..2d155fa 100644
--- a/core/res/res/drawable-ldpi/dialog_divider_horizontal_light.9.png
+++ b/core/res/res/drawable-ldpi/dialog_divider_horizontal_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/divider_horizontal_bright.9.png b/core/res/res/drawable-ldpi/divider_horizontal_bright.9.png
index 24f2a3f..a50d559 100644
--- a/core/res/res/drawable-ldpi/divider_horizontal_bright.9.png
+++ b/core/res/res/drawable-ldpi/divider_horizontal_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/divider_horizontal_bright_opaque.9.png b/core/res/res/drawable-ldpi/divider_horizontal_bright_opaque.9.png
index 24f2a3f..a50d559 100644
--- a/core/res/res/drawable-ldpi/divider_horizontal_bright_opaque.9.png
+++ b/core/res/res/drawable-ldpi/divider_horizontal_bright_opaque.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/divider_horizontal_dark.9.png b/core/res/res/drawable-ldpi/divider_horizontal_dark.9.png
index 470be26..8d346cc 100644
--- a/core/res/res/drawable-ldpi/divider_horizontal_dark.9.png
+++ b/core/res/res/drawable-ldpi/divider_horizontal_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/divider_horizontal_dark_opaque.9.png b/core/res/res/drawable-ldpi/divider_horizontal_dark_opaque.9.png
index 24f2a3f..a50d559 100644
--- a/core/res/res/drawable-ldpi/divider_horizontal_dark_opaque.9.png
+++ b/core/res/res/drawable-ldpi/divider_horizontal_dark_opaque.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/divider_horizontal_dim_dark.9.png b/core/res/res/drawable-ldpi/divider_horizontal_dim_dark.9.png
index e04b49d..0bf977d 100644
--- a/core/res/res/drawable-ldpi/divider_horizontal_dim_dark.9.png
+++ b/core/res/res/drawable-ldpi/divider_horizontal_dim_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/divider_horizontal_textfield.9.png b/core/res/res/drawable-ldpi/divider_horizontal_textfield.9.png
index 547b180..1d18c67 100644
--- a/core/res/res/drawable-ldpi/divider_horizontal_textfield.9.png
+++ b/core/res/res/drawable-ldpi/divider_horizontal_textfield.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/divider_vertical_bright.9.png b/core/res/res/drawable-ldpi/divider_vertical_bright.9.png
index c85f7ab..6196aec 100644
--- a/core/res/res/drawable-ldpi/divider_vertical_bright.9.png
+++ b/core/res/res/drawable-ldpi/divider_vertical_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/divider_vertical_bright_opaque.9.png b/core/res/res/drawable-ldpi/divider_vertical_bright_opaque.9.png
index 662e033..e8f63d5 100644
--- a/core/res/res/drawable-ldpi/divider_vertical_bright_opaque.9.png
+++ b/core/res/res/drawable-ldpi/divider_vertical_bright_opaque.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/divider_vertical_dark.9.png b/core/res/res/drawable-ldpi/divider_vertical_dark.9.png
index 470be26..8d346cc 100644
--- a/core/res/res/drawable-ldpi/divider_vertical_dark.9.png
+++ b/core/res/res/drawable-ldpi/divider_vertical_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/divider_vertical_dark_opaque.9.png b/core/res/res/drawable-ldpi/divider_vertical_dark_opaque.9.png
index 94d2fda..6acf3f2 100644
--- a/core/res/res/drawable-ldpi/divider_vertical_dark_opaque.9.png
+++ b/core/res/res/drawable-ldpi/divider_vertical_dark_opaque.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/editbox_background_focus_yellow.9.png b/core/res/res/drawable-ldpi/editbox_background_focus_yellow.9.png
index f8d65bc..600a853 100644
--- a/core/res/res/drawable-ldpi/editbox_background_focus_yellow.9.png
+++ b/core/res/res/drawable-ldpi/editbox_background_focus_yellow.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/editbox_background_normal.9.png b/core/res/res/drawable-ldpi/editbox_background_normal.9.png
index f8fb178..685c731 100644
--- a/core/res/res/drawable-ldpi/editbox_background_normal.9.png
+++ b/core/res/res/drawable-ldpi/editbox_background_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/editbox_dropdown_background.9.png b/core/res/res/drawable-ldpi/editbox_dropdown_background.9.png
index 8717d34..904537e 100644
--- a/core/res/res/drawable-ldpi/editbox_dropdown_background.9.png
+++ b/core/res/res/drawable-ldpi/editbox_dropdown_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/editbox_dropdown_background_dark.9.png b/core/res/res/drawable-ldpi/editbox_dropdown_background_dark.9.png
index 18885fc..a43bfc0 100644
--- a/core/res/res/drawable-ldpi/editbox_dropdown_background_dark.9.png
+++ b/core/res/res/drawable-ldpi/editbox_dropdown_background_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/emo_im_angel.png b/core/res/res/drawable-ldpi/emo_im_angel.png
index eb74cb3..1bc388f 100644
--- a/core/res/res/drawable-ldpi/emo_im_angel.png
+++ b/core/res/res/drawable-ldpi/emo_im_angel.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/emo_im_cool.png b/core/res/res/drawable-ldpi/emo_im_cool.png
index 657de3b..7005f52 100644
--- a/core/res/res/drawable-ldpi/emo_im_cool.png
+++ b/core/res/res/drawable-ldpi/emo_im_cool.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/emo_im_crying.png b/core/res/res/drawable-ldpi/emo_im_crying.png
index 292cf0c..4429e3b 100644
--- a/core/res/res/drawable-ldpi/emo_im_crying.png
+++ b/core/res/res/drawable-ldpi/emo_im_crying.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/emo_im_foot_in_mouth.png b/core/res/res/drawable-ldpi/emo_im_foot_in_mouth.png
index b1d9983..27158a9ea 100644
--- a/core/res/res/drawable-ldpi/emo_im_foot_in_mouth.png
+++ b/core/res/res/drawable-ldpi/emo_im_foot_in_mouth.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/emo_im_happy.png b/core/res/res/drawable-ldpi/emo_im_happy.png
index b34a54b..e4e98fa 100644
--- a/core/res/res/drawable-ldpi/emo_im_happy.png
+++ b/core/res/res/drawable-ldpi/emo_im_happy.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/emo_im_kissing.png b/core/res/res/drawable-ldpi/emo_im_kissing.png
index d8aaf11..98bdeb8 100644
--- a/core/res/res/drawable-ldpi/emo_im_kissing.png
+++ b/core/res/res/drawable-ldpi/emo_im_kissing.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/emo_im_laughing.png b/core/res/res/drawable-ldpi/emo_im_laughing.png
index 41ddb6f..b90f852 100644
--- a/core/res/res/drawable-ldpi/emo_im_laughing.png
+++ b/core/res/res/drawable-ldpi/emo_im_laughing.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/emo_im_lips_are_sealed.png b/core/res/res/drawable-ldpi/emo_im_lips_are_sealed.png
index 85d0c42..ea73077 100644
--- a/core/res/res/drawable-ldpi/emo_im_lips_are_sealed.png
+++ b/core/res/res/drawable-ldpi/emo_im_lips_are_sealed.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/emo_im_money_mouth.png b/core/res/res/drawable-ldpi/emo_im_money_mouth.png
index b04a56c..3f47743 100644
--- a/core/res/res/drawable-ldpi/emo_im_money_mouth.png
+++ b/core/res/res/drawable-ldpi/emo_im_money_mouth.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/emo_im_sad.png b/core/res/res/drawable-ldpi/emo_im_sad.png
index e978231..5b216e2 100644
--- a/core/res/res/drawable-ldpi/emo_im_sad.png
+++ b/core/res/res/drawable-ldpi/emo_im_sad.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/emo_im_surprised.png b/core/res/res/drawable-ldpi/emo_im_surprised.png
index 6f9c8d9..3ff045b 100644
--- a/core/res/res/drawable-ldpi/emo_im_surprised.png
+++ b/core/res/res/drawable-ldpi/emo_im_surprised.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/emo_im_tongue_sticking_out.png b/core/res/res/drawable-ldpi/emo_im_tongue_sticking_out.png
index c62447c..313e99a 100644
--- a/core/res/res/drawable-ldpi/emo_im_tongue_sticking_out.png
+++ b/core/res/res/drawable-ldpi/emo_im_tongue_sticking_out.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/emo_im_undecided.png b/core/res/res/drawable-ldpi/emo_im_undecided.png
index 27c4ca3..5e39854 100644
--- a/core/res/res/drawable-ldpi/emo_im_undecided.png
+++ b/core/res/res/drawable-ldpi/emo_im_undecided.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/emo_im_winking.png b/core/res/res/drawable-ldpi/emo_im_winking.png
index 97b180f..bf922d8 100644
--- a/core/res/res/drawable-ldpi/emo_im_winking.png
+++ b/core/res/res/drawable-ldpi/emo_im_winking.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/emo_im_wtf.png b/core/res/res/drawable-ldpi/emo_im_wtf.png
index 8d6a307..f00b6c4 100644
--- a/core/res/res/drawable-ldpi/emo_im_wtf.png
+++ b/core/res/res/drawable-ldpi/emo_im_wtf.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/emo_im_yelling.png b/core/res/res/drawable-ldpi/emo_im_yelling.png
index ce74375..e63d39b 100644
--- a/core/res/res/drawable-ldpi/emo_im_yelling.png
+++ b/core/res/res/drawable-ldpi/emo_im_yelling.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/expander_ic_maximized.9.png b/core/res/res/drawable-ldpi/expander_ic_maximized.9.png
index 732a6f5..1a0f945 100644
--- a/core/res/res/drawable-ldpi/expander_ic_maximized.9.png
+++ b/core/res/res/drawable-ldpi/expander_ic_maximized.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/expander_ic_minimized.9.png b/core/res/res/drawable-ldpi/expander_ic_minimized.9.png
index 054e3a4..823dbec 100644
--- a/core/res/res/drawable-ldpi/expander_ic_minimized.9.png
+++ b/core/res/res/drawable-ldpi/expander_ic_minimized.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/focused_application_background_static.png b/core/res/res/drawable-ldpi/focused_application_background_static.png
index 8738bad..923d69b 100644
--- a/core/res/res/drawable-ldpi/focused_application_background_static.png
+++ b/core/res/res/drawable-ldpi/focused_application_background_static.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/frame_gallery_thumb.9.png b/core/res/res/drawable-ldpi/frame_gallery_thumb.9.png
index d686b77..239f2b8 100644
--- a/core/res/res/drawable-ldpi/frame_gallery_thumb.9.png
+++ b/core/res/res/drawable-ldpi/frame_gallery_thumb.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/frame_gallery_thumb_pressed.9.png b/core/res/res/drawable-ldpi/frame_gallery_thumb_pressed.9.png
index c33048a..a74ef1e4 100644
--- a/core/res/res/drawable-ldpi/frame_gallery_thumb_pressed.9.png
+++ b/core/res/res/drawable-ldpi/frame_gallery_thumb_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/frame_gallery_thumb_selected.9.png b/core/res/res/drawable-ldpi/frame_gallery_thumb_selected.9.png
index 8c4adbc..770fe8e 100644
--- a/core/res/res/drawable-ldpi/frame_gallery_thumb_selected.9.png
+++ b/core/res/res/drawable-ldpi/frame_gallery_thumb_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/gallery_selected_default.9.png b/core/res/res/drawable-ldpi/gallery_selected_default.9.png
index 3d55225b..0d96ee4 100644
--- a/core/res/res/drawable-ldpi/gallery_selected_default.9.png
+++ b/core/res/res/drawable-ldpi/gallery_selected_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/gallery_selected_focused.9.png b/core/res/res/drawable-ldpi/gallery_selected_focused.9.png
index 31aabc2..a3a4796 100644
--- a/core/res/res/drawable-ldpi/gallery_selected_focused.9.png
+++ b/core/res/res/drawable-ldpi/gallery_selected_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/gallery_selected_pressed.9.png b/core/res/res/drawable-ldpi/gallery_selected_pressed.9.png
index d05a36f..6b5c355 100644
--- a/core/res/res/drawable-ldpi/gallery_selected_pressed.9.png
+++ b/core/res/res/drawable-ldpi/gallery_selected_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/gallery_unselected_default.9.png b/core/res/res/drawable-ldpi/gallery_unselected_default.9.png
index 179c32c..f507828 100644
--- a/core/res/res/drawable-ldpi/gallery_unselected_default.9.png
+++ b/core/res/res/drawable-ldpi/gallery_unselected_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/gallery_unselected_pressed.9.png b/core/res/res/drawable-ldpi/gallery_unselected_pressed.9.png
index 0e3f652..02a4bc3 100644
--- a/core/res/res/drawable-ldpi/gallery_unselected_pressed.9.png
+++ b/core/res/res/drawable-ldpi/gallery_unselected_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/grid_selector_background_focus.9.png b/core/res/res/drawable-ldpi/grid_selector_background_focus.9.png
index 87d47ca..609d9c1 100644
--- a/core/res/res/drawable-ldpi/grid_selector_background_focus.9.png
+++ b/core/res/res/drawable-ldpi/grid_selector_background_focus.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/grid_selector_background_pressed.9.png b/core/res/res/drawable-ldpi/grid_selector_background_pressed.9.png
index f2cc507..dcc7228 100644
--- a/core/res/res/drawable-ldpi/grid_selector_background_pressed.9.png
+++ b/core/res/res/drawable-ldpi/grid_selector_background_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/highlight_disabled.9.png b/core/res/res/drawable-ldpi/highlight_disabled.9.png
index 473bdf6..455f86e 100644
--- a/core/res/res/drawable-ldpi/highlight_disabled.9.png
+++ b/core/res/res/drawable-ldpi/highlight_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/highlight_pressed.9.png b/core/res/res/drawable-ldpi/highlight_pressed.9.png
index 0ebfbde..d76f433 100644
--- a/core/res/res/drawable-ldpi/highlight_pressed.9.png
+++ b/core/res/res/drawable-ldpi/highlight_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/highlight_selected.9.png b/core/res/res/drawable-ldpi/highlight_selected.9.png
index a4df027..9f13ede 100644
--- a/core/res/res/drawable-ldpi/highlight_selected.9.png
+++ b/core/res/res/drawable-ldpi/highlight_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_aggregated.png b/core/res/res/drawable-ldpi/ic_aggregated.png
index fdb2e90..8d88643 100644
--- a/core/res/res/drawable-ldpi/ic_aggregated.png
+++ b/core/res/res/drawable-ldpi/ic_aggregated.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_btn_round_more_disabled.png b/core/res/res/drawable-ldpi/ic_btn_round_more_disabled.png
index 99c7a2f..412e68f 100644
--- a/core/res/res/drawable-ldpi/ic_btn_round_more_disabled.png
+++ b/core/res/res/drawable-ldpi/ic_btn_round_more_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_btn_round_more_normal.png b/core/res/res/drawable-ldpi/ic_btn_round_more_normal.png
index a8cb6d5..9505cc0 100644
--- a/core/res/res/drawable-ldpi/ic_btn_round_more_normal.png
+++ b/core/res/res/drawable-ldpi/ic_btn_round_more_normal.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_btn_search_go.png b/core/res/res/drawable-ldpi/ic_btn_search_go.png
index 94e5555..a3991a6 100644
--- a/core/res/res/drawable-ldpi/ic_btn_search_go.png
+++ b/core/res/res/drawable-ldpi/ic_btn_search_go.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_btn_speak_now.png b/core/res/res/drawable-ldpi/ic_btn_speak_now.png
index 106e8e6..11fbbb1 100644
--- a/core/res/res/drawable-ldpi/ic_btn_speak_now.png
+++ b/core/res/res/drawable-ldpi/ic_btn_speak_now.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_btn_square_browser_zoom_fit_page_disabled.png b/core/res/res/drawable-ldpi/ic_btn_square_browser_zoom_fit_page_disabled.png
index ef71e6c..a54806e 100644
--- a/core/res/res/drawable-ldpi/ic_btn_square_browser_zoom_fit_page_disabled.png
+++ b/core/res/res/drawable-ldpi/ic_btn_square_browser_zoom_fit_page_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_btn_square_browser_zoom_fit_page_normal.png b/core/res/res/drawable-ldpi/ic_btn_square_browser_zoom_fit_page_normal.png
index fc1531c..7e14aa6 100644
--- a/core/res/res/drawable-ldpi/ic_btn_square_browser_zoom_fit_page_normal.png
+++ b/core/res/res/drawable-ldpi/ic_btn_square_browser_zoom_fit_page_normal.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_btn_square_browser_zoom_page_overview_disabled.png b/core/res/res/drawable-ldpi/ic_btn_square_browser_zoom_page_overview_disabled.png
index 84fcf0a..b9a7ba6 100644
--- a/core/res/res/drawable-ldpi/ic_btn_square_browser_zoom_page_overview_disabled.png
+++ b/core/res/res/drawable-ldpi/ic_btn_square_browser_zoom_page_overview_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_btn_square_browser_zoom_page_overview_normal.png b/core/res/res/drawable-ldpi/ic_btn_square_browser_zoom_page_overview_normal.png
index 70fc818..1fb6c6e 100644
--- a/core/res/res/drawable-ldpi/ic_btn_square_browser_zoom_page_overview_normal.png
+++ b/core/res/res/drawable-ldpi/ic_btn_square_browser_zoom_page_overview_normal.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_bullet_key_permission.png b/core/res/res/drawable-ldpi/ic_bullet_key_permission.png
index 4aff20c..59ccd2b 100644
--- a/core/res/res/drawable-ldpi/ic_bullet_key_permission.png
+++ b/core/res/res/drawable-ldpi/ic_bullet_key_permission.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_contact_picture.png b/core/res/res/drawable-ldpi/ic_contact_picture.png
index a0444e4..badc720 100644
--- a/core/res/res/drawable-ldpi/ic_contact_picture.png
+++ b/core/res/res/drawable-ldpi/ic_contact_picture.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_contact_picture_2.png b/core/res/res/drawable-ldpi/ic_contact_picture_2.png
index 42e8d86..325dd03 100644
--- a/core/res/res/drawable-ldpi/ic_contact_picture_2.png
+++ b/core/res/res/drawable-ldpi/ic_contact_picture_2.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_contact_picture_3.png b/core/res/res/drawable-ldpi/ic_contact_picture_3.png
index c9c0a65..406b932 100644
--- a/core/res/res/drawable-ldpi/ic_contact_picture_3.png
+++ b/core/res/res/drawable-ldpi/ic_contact_picture_3.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_delete.png b/core/res/res/drawable-ldpi/ic_delete.png
index a4cefa8..f755aed 100644
--- a/core/res/res/drawable-ldpi/ic_delete.png
+++ b/core/res/res/drawable-ldpi/ic_delete.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_dialog_alert.png b/core/res/res/drawable-ldpi/ic_dialog_alert.png
index 6c3c624..cb8fcc7 100644
--- a/core/res/res/drawable-ldpi/ic_dialog_alert.png
+++ b/core/res/res/drawable-ldpi/ic_dialog_alert.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_dialog_dialer.png b/core/res/res/drawable-ldpi/ic_dialog_dialer.png
index 066efef..18ce557 100644
--- a/core/res/res/drawable-ldpi/ic_dialog_dialer.png
+++ b/core/res/res/drawable-ldpi/ic_dialog_dialer.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_dialog_email.png b/core/res/res/drawable-ldpi/ic_dialog_email.png
index 194222e..6ee48f9 100644
--- a/core/res/res/drawable-ldpi/ic_dialog_email.png
+++ b/core/res/res/drawable-ldpi/ic_dialog_email.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_dialog_info.png b/core/res/res/drawable-ldpi/ic_dialog_info.png
index a1dcc5a..82e1fe4 100644
--- a/core/res/res/drawable-ldpi/ic_dialog_info.png
+++ b/core/res/res/drawable-ldpi/ic_dialog_info.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_dialog_map.png b/core/res/res/drawable-ldpi/ic_dialog_map.png
index 9b04476..f22a011 100644
--- a/core/res/res/drawable-ldpi/ic_dialog_map.png
+++ b/core/res/res/drawable-ldpi/ic_dialog_map.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_dialog_time.png b/core/res/res/drawable-ldpi/ic_dialog_time.png
index 5b8722b..9f6c1e4 100644
--- a/core/res/res/drawable-ldpi/ic_dialog_time.png
+++ b/core/res/res/drawable-ldpi/ic_dialog_time.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_dialog_usb.png b/core/res/res/drawable-ldpi/ic_dialog_usb.png
index eeef46e..386a74a 100644
--- a/core/res/res/drawable-ldpi/ic_dialog_usb.png
+++ b/core/res/res/drawable-ldpi/ic_dialog_usb.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_emergency.png b/core/res/res/drawable-ldpi/ic_emergency.png
index 5c4ed5d..6d12c53 100644
--- a/core/res/res/drawable-ldpi/ic_emergency.png
+++ b/core/res/res/drawable-ldpi/ic_emergency.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_input_add.png b/core/res/res/drawable-ldpi/ic_input_add.png
index 04cc27a..e1fbf1c 100644
--- a/core/res/res/drawable-ldpi/ic_input_add.png
+++ b/core/res/res/drawable-ldpi/ic_input_add.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_input_delete.png b/core/res/res/drawable-ldpi/ic_input_delete.png
index d7eff17..048143d9 100644
--- a/core/res/res/drawable-ldpi/ic_input_delete.png
+++ b/core/res/res/drawable-ldpi/ic_input_delete.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_input_get.png b/core/res/res/drawable-ldpi/ic_input_get.png
index 4452993..48c4f5e7 100644
--- a/core/res/res/drawable-ldpi/ic_input_get.png
+++ b/core/res/res/drawable-ldpi/ic_input_get.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_jog_dial_answer.png b/core/res/res/drawable-ldpi/ic_jog_dial_answer.png
index 9c5800a..124077f 100644
--- a/core/res/res/drawable-ldpi/ic_jog_dial_answer.png
+++ b/core/res/res/drawable-ldpi/ic_jog_dial_answer.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_jog_dial_answer_and_end.png b/core/res/res/drawable-ldpi/ic_jog_dial_answer_and_end.png
index 117c6d8..345aa78 100644
--- a/core/res/res/drawable-ldpi/ic_jog_dial_answer_and_end.png
+++ b/core/res/res/drawable-ldpi/ic_jog_dial_answer_and_end.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_jog_dial_answer_and_hold.png b/core/res/res/drawable-ldpi/ic_jog_dial_answer_and_hold.png
index 08280e3..361e4b1 100644
--- a/core/res/res/drawable-ldpi/ic_jog_dial_answer_and_hold.png
+++ b/core/res/res/drawable-ldpi/ic_jog_dial_answer_and_hold.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_jog_dial_decline.png b/core/res/res/drawable-ldpi/ic_jog_dial_decline.png
index 7ccc1ca..d6c08d8 100644
--- a/core/res/res/drawable-ldpi/ic_jog_dial_decline.png
+++ b/core/res/res/drawable-ldpi/ic_jog_dial_decline.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_jog_dial_sound_off.png b/core/res/res/drawable-ldpi/ic_jog_dial_sound_off.png
index a4e3edf..f9d418a 100644
--- a/core/res/res/drawable-ldpi/ic_jog_dial_sound_off.png
+++ b/core/res/res/drawable-ldpi/ic_jog_dial_sound_off.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_jog_dial_sound_on.png b/core/res/res/drawable-ldpi/ic_jog_dial_sound_on.png
index f8190b56..7e53177 100644
--- a/core/res/res/drawable-ldpi/ic_jog_dial_sound_on.png
+++ b/core/res/res/drawable-ldpi/ic_jog_dial_sound_on.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_jog_dial_unlock.png b/core/res/res/drawable-ldpi/ic_jog_dial_unlock.png
index 16fa0db..2d5d691c 100644
--- a/core/res/res/drawable-ldpi/ic_jog_dial_unlock.png
+++ b/core/res/res/drawable-ldpi/ic_jog_dial_unlock.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_jog_dial_vibrate_on.png b/core/res/res/drawable-ldpi/ic_jog_dial_vibrate_on.png
index ac5a9b9..97a9851 100644
--- a/core/res/res/drawable-ldpi/ic_jog_dial_vibrate_on.png
+++ b/core/res/res/drawable-ldpi/ic_jog_dial_vibrate_on.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_launcher_android.png b/core/res/res/drawable-ldpi/ic_launcher_android.png
index 245e4b7..9957175 100644
--- a/core/res/res/drawable-ldpi/ic_launcher_android.png
+++ b/core/res/res/drawable-ldpi/ic_launcher_android.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_lock_airplane_mode_alpha.png b/core/res/res/drawable-ldpi/ic_lock_airplane_mode_alpha.png
index 65a101b..93b3c33 100644
--- a/core/res/res/drawable-ldpi/ic_lock_airplane_mode_alpha.png
+++ b/core/res/res/drawable-ldpi/ic_lock_airplane_mode_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_lock_airplane_mode_off_am_alpha.png b/core/res/res/drawable-ldpi/ic_lock_airplane_mode_off_am_alpha.png
index 11adeb8..de67815 100644
--- a/core/res/res/drawable-ldpi/ic_lock_airplane_mode_off_am_alpha.png
+++ b/core/res/res/drawable-ldpi/ic_lock_airplane_mode_off_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_lock_idle_alarm_alpha.png b/core/res/res/drawable-ldpi/ic_lock_idle_alarm_alpha.png
index dc133c5..bdb2c98 100644
--- a/core/res/res/drawable-ldpi/ic_lock_idle_alarm_alpha.png
+++ b/core/res/res/drawable-ldpi/ic_lock_idle_alarm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_lock_idle_charging.png b/core/res/res/drawable-ldpi/ic_lock_idle_charging.png
index c943b67..90009ec 100644
--- a/core/res/res/drawable-ldpi/ic_lock_idle_charging.png
+++ b/core/res/res/drawable-ldpi/ic_lock_idle_charging.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_lock_idle_lock.png b/core/res/res/drawable-ldpi/ic_lock_idle_lock.png
index bc4adfd..061d2a0 100644
--- a/core/res/res/drawable-ldpi/ic_lock_idle_lock.png
+++ b/core/res/res/drawable-ldpi/ic_lock_idle_lock.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_lock_idle_low_battery.png b/core/res/res/drawable-ldpi/ic_lock_idle_low_battery.png
index df7cb22..aba35d6 100644
--- a/core/res/res/drawable-ldpi/ic_lock_idle_low_battery.png
+++ b/core/res/res/drawable-ldpi/ic_lock_idle_low_battery.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_lock_lock_alpha.png b/core/res/res/drawable-ldpi/ic_lock_lock_alpha.png
index bde40f6..a9e33d5 100644
--- a/core/res/res/drawable-ldpi/ic_lock_lock_alpha.png
+++ b/core/res/res/drawable-ldpi/ic_lock_lock_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_lock_power_off_alpha.png b/core/res/res/drawable-ldpi/ic_lock_power_off_alpha.png
index 074d6d0..e67c933 100644
--- a/core/res/res/drawable-ldpi/ic_lock_power_off_alpha.png
+++ b/core/res/res/drawable-ldpi/ic_lock_power_off_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_lock_ringer_off_alpha.png b/core/res/res/drawable-ldpi/ic_lock_ringer_off_alpha.png
index 50ff3de..c1150945 100644
--- a/core/res/res/drawable-ldpi/ic_lock_ringer_off_alpha.png
+++ b/core/res/res/drawable-ldpi/ic_lock_ringer_off_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_lock_ringer_on_alpha.png b/core/res/res/drawable-ldpi/ic_lock_ringer_on_alpha.png
index 7232728..ac129d2 100644
--- a/core/res/res/drawable-ldpi/ic_lock_ringer_on_alpha.png
+++ b/core/res/res/drawable-ldpi/ic_lock_ringer_on_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_lock_silent_mode.png b/core/res/res/drawable-ldpi/ic_lock_silent_mode.png
index 8004f9d..f5b40e3 100644
--- a/core/res/res/drawable-ldpi/ic_lock_silent_mode.png
+++ b/core/res/res/drawable-ldpi/ic_lock_silent_mode.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_lock_silent_mode_off.png b/core/res/res/drawable-ldpi/ic_lock_silent_mode_off.png
index 81b7a8d..f6a3d64 100644
--- a/core/res/res/drawable-ldpi/ic_lock_silent_mode_off.png
+++ b/core/res/res/drawable-ldpi/ic_lock_silent_mode_off.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_lock_silent_mode_vibrate.png b/core/res/res/drawable-ldpi/ic_lock_silent_mode_vibrate.png
index 5f54f6f..9a27b62 100644
--- a/core/res/res/drawable-ldpi/ic_lock_silent_mode_vibrate.png
+++ b/core/res/res/drawable-ldpi/ic_lock_silent_mode_vibrate.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_maps_indicator_current_position.png b/core/res/res/drawable-ldpi/ic_maps_indicator_current_position.png
index 697b065..0bde4da 100644
--- a/core/res/res/drawable-ldpi/ic_maps_indicator_current_position.png
+++ b/core/res/res/drawable-ldpi/ic_maps_indicator_current_position.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_maps_indicator_current_position_anim1.png b/core/res/res/drawable-ldpi/ic_maps_indicator_current_position_anim1.png
index 15a8a08..a7c15c9 100644
--- a/core/res/res/drawable-ldpi/ic_maps_indicator_current_position_anim1.png
+++ b/core/res/res/drawable-ldpi/ic_maps_indicator_current_position_anim1.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_maps_indicator_current_position_anim2.png b/core/res/res/drawable-ldpi/ic_maps_indicator_current_position_anim2.png
index f8b8de2..de60b81 100644
--- a/core/res/res/drawable-ldpi/ic_maps_indicator_current_position_anim2.png
+++ b/core/res/res/drawable-ldpi/ic_maps_indicator_current_position_anim2.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_maps_indicator_current_position_anim3.png b/core/res/res/drawable-ldpi/ic_maps_indicator_current_position_anim3.png
index 02f7547..e65c6fa 100644
--- a/core/res/res/drawable-ldpi/ic_maps_indicator_current_position_anim3.png
+++ b/core/res/res/drawable-ldpi/ic_maps_indicator_current_position_anim3.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_media_embed_play.png b/core/res/res/drawable-ldpi/ic_media_embed_play.png
index e7c1972..fa5b9ae 100644
--- a/core/res/res/drawable-ldpi/ic_media_embed_play.png
+++ b/core/res/res/drawable-ldpi/ic_media_embed_play.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_media_ff.png b/core/res/res/drawable-ldpi/ic_media_ff.png
index 1b4d9db..7e73b2a 100644
--- a/core/res/res/drawable-ldpi/ic_media_ff.png
+++ b/core/res/res/drawable-ldpi/ic_media_ff.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_media_fullscreen.png b/core/res/res/drawable-ldpi/ic_media_fullscreen.png
index 1a38c38..6023203 100644
--- a/core/res/res/drawable-ldpi/ic_media_fullscreen.png
+++ b/core/res/res/drawable-ldpi/ic_media_fullscreen.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_media_next.png b/core/res/res/drawable-ldpi/ic_media_next.png
index 99927fd..33cd127 100644
--- a/core/res/res/drawable-ldpi/ic_media_next.png
+++ b/core/res/res/drawable-ldpi/ic_media_next.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_media_pause.png b/core/res/res/drawable-ldpi/ic_media_pause.png
index 3b98d66..f181b4e 100644
--- a/core/res/res/drawable-ldpi/ic_media_pause.png
+++ b/core/res/res/drawable-ldpi/ic_media_pause.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_media_play.png b/core/res/res/drawable-ldpi/ic_media_play.png
index e7c1972..fa5b9ae 100644
--- a/core/res/res/drawable-ldpi/ic_media_play.png
+++ b/core/res/res/drawable-ldpi/ic_media_play.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_media_previous.png b/core/res/res/drawable-ldpi/ic_media_previous.png
index df04322..574fed3 100644
--- a/core/res/res/drawable-ldpi/ic_media_previous.png
+++ b/core/res/res/drawable-ldpi/ic_media_previous.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_media_rew.png b/core/res/res/drawable-ldpi/ic_media_rew.png
index 28843f9..b36102c 100644
--- a/core/res/res/drawable-ldpi/ic_media_rew.png
+++ b/core/res/res/drawable-ldpi/ic_media_rew.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_media_video_poster.png b/core/res/res/drawable-ldpi/ic_media_video_poster.png
index 7b34913..0a6369f 100644
--- a/core/res/res/drawable-ldpi/ic_media_video_poster.png
+++ b/core/res/res/drawable-ldpi/ic_media_video_poster.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_account_list.png b/core/res/res/drawable-ldpi/ic_menu_account_list.png
index 04ededd38..4418827 100644
--- a/core/res/res/drawable-ldpi/ic_menu_account_list.png
+++ b/core/res/res/drawable-ldpi/ic_menu_account_list.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_add.png b/core/res/res/drawable-ldpi/ic_menu_add.png
index 89620af..10175ae 100644
--- a/core/res/res/drawable-ldpi/ic_menu_add.png
+++ b/core/res/res/drawable-ldpi/ic_menu_add.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_agenda.png b/core/res/res/drawable-ldpi/ic_menu_agenda.png
index 9abcc68..ab5206f 100644
--- a/core/res/res/drawable-ldpi/ic_menu_agenda.png
+++ b/core/res/res/drawable-ldpi/ic_menu_agenda.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_allfriends.png b/core/res/res/drawable-ldpi/ic_menu_allfriends.png
index 462d078..4c6c999 100644
--- a/core/res/res/drawable-ldpi/ic_menu_allfriends.png
+++ b/core/res/res/drawable-ldpi/ic_menu_allfriends.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_always_landscape_portrait.png b/core/res/res/drawable-ldpi/ic_menu_always_landscape_portrait.png
index 2c779ca..af7cafd 100644
--- a/core/res/res/drawable-ldpi/ic_menu_always_landscape_portrait.png
+++ b/core/res/res/drawable-ldpi/ic_menu_always_landscape_portrait.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_archive.png b/core/res/res/drawable-ldpi/ic_menu_archive.png
index 719ecd8..614f59f 100644
--- a/core/res/res/drawable-ldpi/ic_menu_archive.png
+++ b/core/res/res/drawable-ldpi/ic_menu_archive.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_attachment.png b/core/res/res/drawable-ldpi/ic_menu_attachment.png
index 8fc2211..fe2b549 100644
--- a/core/res/res/drawable-ldpi/ic_menu_attachment.png
+++ b/core/res/res/drawable-ldpi/ic_menu_attachment.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_back.png b/core/res/res/drawable-ldpi/ic_menu_back.png
index 71eb533..d3e942f 100644
--- a/core/res/res/drawable-ldpi/ic_menu_back.png
+++ b/core/res/res/drawable-ldpi/ic_menu_back.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_block.png b/core/res/res/drawable-ldpi/ic_menu_block.png
index c8d80cd..bc2707e 100644
--- a/core/res/res/drawable-ldpi/ic_menu_block.png
+++ b/core/res/res/drawable-ldpi/ic_menu_block.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_blocked_user.png b/core/res/res/drawable-ldpi/ic_menu_blocked_user.png
index c6407b5..37fc379 100644
--- a/core/res/res/drawable-ldpi/ic_menu_blocked_user.png
+++ b/core/res/res/drawable-ldpi/ic_menu_blocked_user.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_call.png b/core/res/res/drawable-ldpi/ic_menu_call.png
index 39d4b10..5a5f8d7 100644
--- a/core/res/res/drawable-ldpi/ic_menu_call.png
+++ b/core/res/res/drawable-ldpi/ic_menu_call.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_camera.png b/core/res/res/drawable-ldpi/ic_menu_camera.png
index 4d3a6a5..0f7b7c4 100644
--- a/core/res/res/drawable-ldpi/ic_menu_camera.png
+++ b/core/res/res/drawable-ldpi/ic_menu_camera.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_cc_am.png b/core/res/res/drawable-ldpi/ic_menu_cc_am.png
index d90d70d..aba3211 100644
--- a/core/res/res/drawable-ldpi/ic_menu_cc_am.png
+++ b/core/res/res/drawable-ldpi/ic_menu_cc_am.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_chat_dashboard.png b/core/res/res/drawable-ldpi/ic_menu_chat_dashboard.png
index c417faa..83ca18d 100644
--- a/core/res/res/drawable-ldpi/ic_menu_chat_dashboard.png
+++ b/core/res/res/drawable-ldpi/ic_menu_chat_dashboard.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_clear_playlist.png b/core/res/res/drawable-ldpi/ic_menu_clear_playlist.png
index f3e6b51c..e8a411a 100644
--- a/core/res/res/drawable-ldpi/ic_menu_clear_playlist.png
+++ b/core/res/res/drawable-ldpi/ic_menu_clear_playlist.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_close_clear_cancel.png b/core/res/res/drawable-ldpi/ic_menu_close_clear_cancel.png
index 760b925..2e3d48a 100644
--- a/core/res/res/drawable-ldpi/ic_menu_close_clear_cancel.png
+++ b/core/res/res/drawable-ldpi/ic_menu_close_clear_cancel.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_compass.png b/core/res/res/drawable-ldpi/ic_menu_compass.png
index bf1724b..c72d2f4 100644
--- a/core/res/res/drawable-ldpi/ic_menu_compass.png
+++ b/core/res/res/drawable-ldpi/ic_menu_compass.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_compose.png b/core/res/res/drawable-ldpi/ic_menu_compose.png
index 1e6767b..0459ac3 100644
--- a/core/res/res/drawable-ldpi/ic_menu_compose.png
+++ b/core/res/res/drawable-ldpi/ic_menu_compose.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_crop.png b/core/res/res/drawable-ldpi/ic_menu_crop.png
index 97c9182..9b4cdea 100644
--- a/core/res/res/drawable-ldpi/ic_menu_crop.png
+++ b/core/res/res/drawable-ldpi/ic_menu_crop.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_day.png b/core/res/res/drawable-ldpi/ic_menu_day.png
index f0d661b..f31f63a 100644
--- a/core/res/res/drawable-ldpi/ic_menu_day.png
+++ b/core/res/res/drawable-ldpi/ic_menu_day.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_delete.png b/core/res/res/drawable-ldpi/ic_menu_delete.png
index dbad3dd..b76198f 100644
--- a/core/res/res/drawable-ldpi/ic_menu_delete.png
+++ b/core/res/res/drawable-ldpi/ic_menu_delete.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_directions.png b/core/res/res/drawable-ldpi/ic_menu_directions.png
index 5d89d46..fc78202 100644
--- a/core/res/res/drawable-ldpi/ic_menu_directions.png
+++ b/core/res/res/drawable-ldpi/ic_menu_directions.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_edit.png b/core/res/res/drawable-ldpi/ic_menu_edit.png
index 9bb66e3..2c952b3 100644
--- a/core/res/res/drawable-ldpi/ic_menu_edit.png
+++ b/core/res/res/drawable-ldpi/ic_menu_edit.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_emoticons.png b/core/res/res/drawable-ldpi/ic_menu_emoticons.png
index a97db87..8a54c41 100644
--- a/core/res/res/drawable-ldpi/ic_menu_emoticons.png
+++ b/core/res/res/drawable-ldpi/ic_menu_emoticons.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_end_conversation.png b/core/res/res/drawable-ldpi/ic_menu_end_conversation.png
index dd2005e..cd8d11d 100644
--- a/core/res/res/drawable-ldpi/ic_menu_end_conversation.png
+++ b/core/res/res/drawable-ldpi/ic_menu_end_conversation.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_forward.png b/core/res/res/drawable-ldpi/ic_menu_forward.png
index 554cfb7..6f9ba60 100644
--- a/core/res/res/drawable-ldpi/ic_menu_forward.png
+++ b/core/res/res/drawable-ldpi/ic_menu_forward.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_friendslist.png b/core/res/res/drawable-ldpi/ic_menu_friendslist.png
index 62950da..e1ae642 100644
--- a/core/res/res/drawable-ldpi/ic_menu_friendslist.png
+++ b/core/res/res/drawable-ldpi/ic_menu_friendslist.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_gallery.png b/core/res/res/drawable-ldpi/ic_menu_gallery.png
index d57b284..6847248 100644
--- a/core/res/res/drawable-ldpi/ic_menu_gallery.png
+++ b/core/res/res/drawable-ldpi/ic_menu_gallery.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_goto.png b/core/res/res/drawable-ldpi/ic_menu_goto.png
index d15ea3d..5d3d5a173 100644
--- a/core/res/res/drawable-ldpi/ic_menu_goto.png
+++ b/core/res/res/drawable-ldpi/ic_menu_goto.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_help.png b/core/res/res/drawable-ldpi/ic_menu_help.png
index f93a4e6..7fe3792 100644
--- a/core/res/res/drawable-ldpi/ic_menu_help.png
+++ b/core/res/res/drawable-ldpi/ic_menu_help.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_home.png b/core/res/res/drawable-ldpi/ic_menu_home.png
index fd6f453..0854d20 100644
--- a/core/res/res/drawable-ldpi/ic_menu_home.png
+++ b/core/res/res/drawable-ldpi/ic_menu_home.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_info_details.png b/core/res/res/drawable-ldpi/ic_menu_info_details.png
index 55c57d5..6f14990 100644
--- a/core/res/res/drawable-ldpi/ic_menu_info_details.png
+++ b/core/res/res/drawable-ldpi/ic_menu_info_details.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_invite.png b/core/res/res/drawable-ldpi/ic_menu_invite.png
index 16de8fe1..4f9a822 100644
--- a/core/res/res/drawable-ldpi/ic_menu_invite.png
+++ b/core/res/res/drawable-ldpi/ic_menu_invite.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_login.png b/core/res/res/drawable-ldpi/ic_menu_login.png
index d4181de..daaf6a2 100644
--- a/core/res/res/drawable-ldpi/ic_menu_login.png
+++ b/core/res/res/drawable-ldpi/ic_menu_login.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_manage.png b/core/res/res/drawable-ldpi/ic_menu_manage.png
index b137b8c..6988fb0 100644
--- a/core/res/res/drawable-ldpi/ic_menu_manage.png
+++ b/core/res/res/drawable-ldpi/ic_menu_manage.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_mapmode.png b/core/res/res/drawable-ldpi/ic_menu_mapmode.png
index 8851005..dc1df94 100644
--- a/core/res/res/drawable-ldpi/ic_menu_mapmode.png
+++ b/core/res/res/drawable-ldpi/ic_menu_mapmode.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_mark.png b/core/res/res/drawable-ldpi/ic_menu_mark.png
index 1d44027..3704b16 100644
--- a/core/res/res/drawable-ldpi/ic_menu_mark.png
+++ b/core/res/res/drawable-ldpi/ic_menu_mark.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_month.png b/core/res/res/drawable-ldpi/ic_menu_month.png
index a3462f6..76cee8c 100644
--- a/core/res/res/drawable-ldpi/ic_menu_month.png
+++ b/core/res/res/drawable-ldpi/ic_menu_month.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_more.png b/core/res/res/drawable-ldpi/ic_menu_more.png
index 9296554..c1978ec 100644
--- a/core/res/res/drawable-ldpi/ic_menu_more.png
+++ b/core/res/res/drawable-ldpi/ic_menu_more.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_my_calendar.png b/core/res/res/drawable-ldpi/ic_menu_my_calendar.png
index db3a8b5..ee70312 100644
--- a/core/res/res/drawable-ldpi/ic_menu_my_calendar.png
+++ b/core/res/res/drawable-ldpi/ic_menu_my_calendar.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_mylocation.png b/core/res/res/drawable-ldpi/ic_menu_mylocation.png
index 2db7867..9467767 100644
--- a/core/res/res/drawable-ldpi/ic_menu_mylocation.png
+++ b/core/res/res/drawable-ldpi/ic_menu_mylocation.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_myplaces.png b/core/res/res/drawable-ldpi/ic_menu_myplaces.png
index 9d2e8dc..bda0b24 100644
--- a/core/res/res/drawable-ldpi/ic_menu_myplaces.png
+++ b/core/res/res/drawable-ldpi/ic_menu_myplaces.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_notifications.png b/core/res/res/drawable-ldpi/ic_menu_notifications.png
index 0a22b32..5bc4030 100644
--- a/core/res/res/drawable-ldpi/ic_menu_notifications.png
+++ b/core/res/res/drawable-ldpi/ic_menu_notifications.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_play_clip.png b/core/res/res/drawable-ldpi/ic_menu_play_clip.png
index 7d0f11e..1586eea 100644
--- a/core/res/res/drawable-ldpi/ic_menu_play_clip.png
+++ b/core/res/res/drawable-ldpi/ic_menu_play_clip.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_preferences.png b/core/res/res/drawable-ldpi/ic_menu_preferences.png
index efc2f3e..8a20363 100644
--- a/core/res/res/drawable-ldpi/ic_menu_preferences.png
+++ b/core/res/res/drawable-ldpi/ic_menu_preferences.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_recent_history.png b/core/res/res/drawable-ldpi/ic_menu_recent_history.png
index c75f6e3..cf4cb61 100644
--- a/core/res/res/drawable-ldpi/ic_menu_recent_history.png
+++ b/core/res/res/drawable-ldpi/ic_menu_recent_history.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_report_image.png b/core/res/res/drawable-ldpi/ic_menu_report_image.png
index f2c3a90..6ad82f3 100644
--- a/core/res/res/drawable-ldpi/ic_menu_report_image.png
+++ b/core/res/res/drawable-ldpi/ic_menu_report_image.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_revert.png b/core/res/res/drawable-ldpi/ic_menu_revert.png
index b0f2c60..7dc82da 100644
--- a/core/res/res/drawable-ldpi/ic_menu_revert.png
+++ b/core/res/res/drawable-ldpi/ic_menu_revert.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_rotate.png b/core/res/res/drawable-ldpi/ic_menu_rotate.png
index 34dcbce..653fba3 100644
--- a/core/res/res/drawable-ldpi/ic_menu_rotate.png
+++ b/core/res/res/drawable-ldpi/ic_menu_rotate.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_save.png b/core/res/res/drawable-ldpi/ic_menu_save.png
index ac053b4..10c8bc6 100644
--- a/core/res/res/drawable-ldpi/ic_menu_save.png
+++ b/core/res/res/drawable-ldpi/ic_menu_save.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_search.png b/core/res/res/drawable-ldpi/ic_menu_search.png
index 1d95408..5459c9a 100644
--- a/core/res/res/drawable-ldpi/ic_menu_search.png
+++ b/core/res/res/drawable-ldpi/ic_menu_search.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_send.png b/core/res/res/drawable-ldpi/ic_menu_send.png
index 9043c11..c4edf1c 100644
--- a/core/res/res/drawable-ldpi/ic_menu_send.png
+++ b/core/res/res/drawable-ldpi/ic_menu_send.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_set_as.png b/core/res/res/drawable-ldpi/ic_menu_set_as.png
index d1997d3..229ef65 100644
--- a/core/res/res/drawable-ldpi/ic_menu_set_as.png
+++ b/core/res/res/drawable-ldpi/ic_menu_set_as.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_share.png b/core/res/res/drawable-ldpi/ic_menu_share.png
index f58d231..11ab4b0 100644
--- a/core/res/res/drawable-ldpi/ic_menu_share.png
+++ b/core/res/res/drawable-ldpi/ic_menu_share.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_slideshow.png b/core/res/res/drawable-ldpi/ic_menu_slideshow.png
index a0625c4..4f6e15e 100644
--- a/core/res/res/drawable-ldpi/ic_menu_slideshow.png
+++ b/core/res/res/drawable-ldpi/ic_menu_slideshow.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_sort_alphabetically.png b/core/res/res/drawable-ldpi/ic_menu_sort_alphabetically.png
index 438e854..19148db 100644
--- a/core/res/res/drawable-ldpi/ic_menu_sort_alphabetically.png
+++ b/core/res/res/drawable-ldpi/ic_menu_sort_alphabetically.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_sort_by_size.png b/core/res/res/drawable-ldpi/ic_menu_sort_by_size.png
index bb95da7..7ae4931 100644
--- a/core/res/res/drawable-ldpi/ic_menu_sort_by_size.png
+++ b/core/res/res/drawable-ldpi/ic_menu_sort_by_size.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_star.png b/core/res/res/drawable-ldpi/ic_menu_star.png
index b88f010..d7d4a05 100644
--- a/core/res/res/drawable-ldpi/ic_menu_star.png
+++ b/core/res/res/drawable-ldpi/ic_menu_star.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_start_conversation.png b/core/res/res/drawable-ldpi/ic_menu_start_conversation.png
index 1e39928..50e873f 100644
--- a/core/res/res/drawable-ldpi/ic_menu_start_conversation.png
+++ b/core/res/res/drawable-ldpi/ic_menu_start_conversation.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_stop.png b/core/res/res/drawable-ldpi/ic_menu_stop.png
index d185ae2..bb9461d 100644
--- a/core/res/res/drawable-ldpi/ic_menu_stop.png
+++ b/core/res/res/drawable-ldpi/ic_menu_stop.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_today.png b/core/res/res/drawable-ldpi/ic_menu_today.png
index 2bff751..f11e797 100644
--- a/core/res/res/drawable-ldpi/ic_menu_today.png
+++ b/core/res/res/drawable-ldpi/ic_menu_today.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_upload.png b/core/res/res/drawable-ldpi/ic_menu_upload.png
index fd64fe1..c5e770d 100644
--- a/core/res/res/drawable-ldpi/ic_menu_upload.png
+++ b/core/res/res/drawable-ldpi/ic_menu_upload.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_upload_you_tube.png b/core/res/res/drawable-ldpi/ic_menu_upload_you_tube.png
index 8fa7005..1a0e665 100644
--- a/core/res/res/drawable-ldpi/ic_menu_upload_you_tube.png
+++ b/core/res/res/drawable-ldpi/ic_menu_upload_you_tube.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_view.png b/core/res/res/drawable-ldpi/ic_menu_view.png
index f1acb3d..01b9088 100644
--- a/core/res/res/drawable-ldpi/ic_menu_view.png
+++ b/core/res/res/drawable-ldpi/ic_menu_view.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_week.png b/core/res/res/drawable-ldpi/ic_menu_week.png
index 0af314b..425d9fc 100644
--- a/core/res/res/drawable-ldpi/ic_menu_week.png
+++ b/core/res/res/drawable-ldpi/ic_menu_week.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_zoom.png b/core/res/res/drawable-ldpi/ic_menu_zoom.png
index ff29184..aacece7 100644
--- a/core/res/res/drawable-ldpi/ic_menu_zoom.png
+++ b/core/res/res/drawable-ldpi/ic_menu_zoom.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_notification_clear_all.png b/core/res/res/drawable-ldpi/ic_notification_clear_all.png
index e779740..d2cb2df 100644
--- a/core/res/res/drawable-ldpi/ic_notification_clear_all.png
+++ b/core/res/res/drawable-ldpi/ic_notification_clear_all.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_notification_overlay.9.png b/core/res/res/drawable-ldpi/ic_notification_overlay.9.png
index 771fa73..0020085 100644
--- a/core/res/res/drawable-ldpi/ic_notification_overlay.9.png
+++ b/core/res/res/drawable-ldpi/ic_notification_overlay.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_partial_secure.png b/core/res/res/drawable-ldpi/ic_partial_secure.png
index a9c05b1..ddfc87a 100644
--- a/core/res/res/drawable-ldpi/ic_partial_secure.png
+++ b/core/res/res/drawable-ldpi/ic_partial_secure.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_popup_disk_full.png b/core/res/res/drawable-ldpi/ic_popup_disk_full.png
index f613f38..cd67bc1 100644
--- a/core/res/res/drawable-ldpi/ic_popup_disk_full.png
+++ b/core/res/res/drawable-ldpi/ic_popup_disk_full.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_popup_reminder.png b/core/res/res/drawable-ldpi/ic_popup_reminder.png
index 332daef..f308544 100644
--- a/core/res/res/drawable-ldpi/ic_popup_reminder.png
+++ b/core/res/res/drawable-ldpi/ic_popup_reminder.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_popup_sync_1.png b/core/res/res/drawable-ldpi/ic_popup_sync_1.png
index 407e8de..25ac2e713 100644
--- a/core/res/res/drawable-ldpi/ic_popup_sync_1.png
+++ b/core/res/res/drawable-ldpi/ic_popup_sync_1.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_popup_sync_2.png b/core/res/res/drawable-ldpi/ic_popup_sync_2.png
index a867aa7..3184ca6 100644
--- a/core/res/res/drawable-ldpi/ic_popup_sync_2.png
+++ b/core/res/res/drawable-ldpi/ic_popup_sync_2.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_popup_sync_3.png b/core/res/res/drawable-ldpi/ic_popup_sync_3.png
index 77bd3d7..0eb0dca 100644
--- a/core/res/res/drawable-ldpi/ic_popup_sync_3.png
+++ b/core/res/res/drawable-ldpi/ic_popup_sync_3.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_popup_sync_4.png b/core/res/res/drawable-ldpi/ic_popup_sync_4.png
index 131486b..a9c7ff2 100644
--- a/core/res/res/drawable-ldpi/ic_popup_sync_4.png
+++ b/core/res/res/drawable-ldpi/ic_popup_sync_4.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_popup_sync_5.png b/core/res/res/drawable-ldpi/ic_popup_sync_5.png
index 33fded8..fbc9afe 100644
--- a/core/res/res/drawable-ldpi/ic_popup_sync_5.png
+++ b/core/res/res/drawable-ldpi/ic_popup_sync_5.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_popup_sync_6.png b/core/res/res/drawable-ldpi/ic_popup_sync_6.png
index 489dd56..4af4420 100644
--- a/core/res/res/drawable-ldpi/ic_popup_sync_6.png
+++ b/core/res/res/drawable-ldpi/ic_popup_sync_6.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_search_category_default.png b/core/res/res/drawable-ldpi/ic_search_category_default.png
index 1d95408..5459c9a 100644
--- a/core/res/res/drawable-ldpi/ic_search_category_default.png
+++ b/core/res/res/drawable-ldpi/ic_search_category_default.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_secure.png b/core/res/res/drawable-ldpi/ic_secure.png
index 02d74d1..206403a 100644
--- a/core/res/res/drawable-ldpi/ic_secure.png
+++ b/core/res/res/drawable-ldpi/ic_secure.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_vibrate.png b/core/res/res/drawable-ldpi/ic_vibrate.png
index 726e9dc..242cdc9 100644
--- a/core/res/res/drawable-ldpi/ic_vibrate.png
+++ b/core/res/res/drawable-ldpi/ic_vibrate.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_vibrate_small.png b/core/res/res/drawable-ldpi/ic_vibrate_small.png
index 06bfbb51..d34f4a6 100644
--- a/core/res/res/drawable-ldpi/ic_vibrate_small.png
+++ b/core/res/res/drawable-ldpi/ic_vibrate_small.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_volume.png b/core/res/res/drawable-ldpi/ic_volume.png
index b8a3561..a49efc7 100644
--- a/core/res/res/drawable-ldpi/ic_volume.png
+++ b/core/res/res/drawable-ldpi/ic_volume.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_volume_bluetooth_ad2p.png b/core/res/res/drawable-ldpi/ic_volume_bluetooth_ad2p.png
index facfa4c..377f32e 100644
--- a/core/res/res/drawable-ldpi/ic_volume_bluetooth_ad2p.png
+++ b/core/res/res/drawable-ldpi/ic_volume_bluetooth_ad2p.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_volume_bluetooth_in_call.png b/core/res/res/drawable-ldpi/ic_volume_bluetooth_in_call.png
index 298ce6b..db10d1a 100644
--- a/core/res/res/drawable-ldpi/ic_volume_bluetooth_in_call.png
+++ b/core/res/res/drawable-ldpi/ic_volume_bluetooth_in_call.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_volume_off.png b/core/res/res/drawable-ldpi/ic_volume_off.png
index bad1a68..3637aa0 100644
--- a/core/res/res/drawable-ldpi/ic_volume_off.png
+++ b/core/res/res/drawable-ldpi/ic_volume_off.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_volume_off_small.png b/core/res/res/drawable-ldpi/ic_volume_off_small.png
index 5623911..d64b311 100644
--- a/core/res/res/drawable-ldpi/ic_volume_off_small.png
+++ b/core/res/res/drawable-ldpi/ic_volume_off_small.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_volume_small.png b/core/res/res/drawable-ldpi/ic_volume_small.png
index 530f6b4..85f86cf 100644
--- a/core/res/res/drawable-ldpi/ic_volume_small.png
+++ b/core/res/res/drawable-ldpi/ic_volume_small.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/icon_highlight_rectangle.9.png b/core/res/res/drawable-ldpi/icon_highlight_rectangle.9.png
index 27519b2..2c62f12 100644
--- a/core/res/res/drawable-ldpi/icon_highlight_rectangle.9.png
+++ b/core/res/res/drawable-ldpi/icon_highlight_rectangle.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/icon_highlight_square.9.png b/core/res/res/drawable-ldpi/icon_highlight_square.9.png
index 228ef23..afd71a22 100644
--- a/core/res/res/drawable-ldpi/icon_highlight_square.9.png
+++ b/core/res/res/drawable-ldpi/icon_highlight_square.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ime_qwerty.png b/core/res/res/drawable-ldpi/ime_qwerty.png
index 11e26db..607ee7a 100644
--- a/core/res/res/drawable-ldpi/ime_qwerty.png
+++ b/core/res/res/drawable-ldpi/ime_qwerty.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/indicator_input_error.png b/core/res/res/drawable-ldpi/indicator_input_error.png
index f1a804a..5cd43cb 100644
--- a/core/res/res/drawable-ldpi/indicator_input_error.png
+++ b/core/res/res/drawable-ldpi/indicator_input_error.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_dial_arrow_long_left_green.png b/core/res/res/drawable-ldpi/jog_dial_arrow_long_left_green.png
index cb30024..9390216 100644
--- a/core/res/res/drawable-ldpi/jog_dial_arrow_long_left_green.png
+++ b/core/res/res/drawable-ldpi/jog_dial_arrow_long_left_green.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_dial_arrow_long_left_yellow.png b/core/res/res/drawable-ldpi/jog_dial_arrow_long_left_yellow.png
index f63e737..3ffd884 100644
--- a/core/res/res/drawable-ldpi/jog_dial_arrow_long_left_yellow.png
+++ b/core/res/res/drawable-ldpi/jog_dial_arrow_long_left_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_dial_arrow_long_middle_yellow.png b/core/res/res/drawable-ldpi/jog_dial_arrow_long_middle_yellow.png
index 249d53d..800fd86 100644
--- a/core/res/res/drawable-ldpi/jog_dial_arrow_long_middle_yellow.png
+++ b/core/res/res/drawable-ldpi/jog_dial_arrow_long_middle_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_dial_arrow_long_right_red.png b/core/res/res/drawable-ldpi/jog_dial_arrow_long_right_red.png
index 6a338fe..ac551c1 100644
--- a/core/res/res/drawable-ldpi/jog_dial_arrow_long_right_red.png
+++ b/core/res/res/drawable-ldpi/jog_dial_arrow_long_right_red.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_dial_arrow_long_right_yellow.png b/core/res/res/drawable-ldpi/jog_dial_arrow_long_right_yellow.png
index 50f5c47..4ef948b 100644
--- a/core/res/res/drawable-ldpi/jog_dial_arrow_long_right_yellow.png
+++ b/core/res/res/drawable-ldpi/jog_dial_arrow_long_right_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_dial_arrow_short_left.png b/core/res/res/drawable-ldpi/jog_dial_arrow_short_left.png
index a8ed6987..2e37cc0 100644
--- a/core/res/res/drawable-ldpi/jog_dial_arrow_short_left.png
+++ b/core/res/res/drawable-ldpi/jog_dial_arrow_short_left.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_dial_arrow_short_left_and_right.png b/core/res/res/drawable-ldpi/jog_dial_arrow_short_left_and_right.png
index bfd6c4e..1c7ce57 100644
--- a/core/res/res/drawable-ldpi/jog_dial_arrow_short_left_and_right.png
+++ b/core/res/res/drawable-ldpi/jog_dial_arrow_short_left_and_right.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_dial_arrow_short_right.png b/core/res/res/drawable-ldpi/jog_dial_arrow_short_right.png
index d22d508..f0b8abd 100644
--- a/core/res/res/drawable-ldpi/jog_dial_arrow_short_right.png
+++ b/core/res/res/drawable-ldpi/jog_dial_arrow_short_right.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_dial_bg.png b/core/res/res/drawable-ldpi/jog_dial_bg.png
index 263188b..49a82f91 100644
--- a/core/res/res/drawable-ldpi/jog_dial_bg.png
+++ b/core/res/res/drawable-ldpi/jog_dial_bg.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_dial_dimple.png b/core/res/res/drawable-ldpi/jog_dial_dimple.png
index c6f52ef..61242f2 100644
--- a/core/res/res/drawable-ldpi/jog_dial_dimple.png
+++ b/core/res/res/drawable-ldpi/jog_dial_dimple.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_dial_dimple_dim.png b/core/res/res/drawable-ldpi/jog_dial_dimple_dim.png
index b85db4e..f355ecf 100644
--- a/core/res/res/drawable-ldpi/jog_dial_dimple_dim.png
+++ b/core/res/res/drawable-ldpi/jog_dial_dimple_dim.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_tab_bar_left_end_confirm_gray.9.png b/core/res/res/drawable-ldpi/jog_tab_bar_left_end_confirm_gray.9.png
index be9edd1..0e67e49 100644
--- a/core/res/res/drawable-ldpi/jog_tab_bar_left_end_confirm_gray.9.png
+++ b/core/res/res/drawable-ldpi/jog_tab_bar_left_end_confirm_gray.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_tab_bar_left_end_confirm_green.9.png b/core/res/res/drawable-ldpi/jog_tab_bar_left_end_confirm_green.9.png
index 8b445fb..35d392b 100644
--- a/core/res/res/drawable-ldpi/jog_tab_bar_left_end_confirm_green.9.png
+++ b/core/res/res/drawable-ldpi/jog_tab_bar_left_end_confirm_green.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_tab_bar_left_end_confirm_red.9.png b/core/res/res/drawable-ldpi/jog_tab_bar_left_end_confirm_red.9.png
index f9b07f8..5d9cd31 100644
--- a/core/res/res/drawable-ldpi/jog_tab_bar_left_end_confirm_red.9.png
+++ b/core/res/res/drawable-ldpi/jog_tab_bar_left_end_confirm_red.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_tab_bar_left_end_confirm_yellow.9.png b/core/res/res/drawable-ldpi/jog_tab_bar_left_end_confirm_yellow.9.png
index 473fcb0..703f71d 100644
--- a/core/res/res/drawable-ldpi/jog_tab_bar_left_end_confirm_yellow.9.png
+++ b/core/res/res/drawable-ldpi/jog_tab_bar_left_end_confirm_yellow.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_tab_bar_left_end_normal.9.png b/core/res/res/drawable-ldpi/jog_tab_bar_left_end_normal.9.png
index b8ecac7..8aacb71 100644
--- a/core/res/res/drawable-ldpi/jog_tab_bar_left_end_normal.9.png
+++ b/core/res/res/drawable-ldpi/jog_tab_bar_left_end_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_tab_bar_left_end_pressed.9.png b/core/res/res/drawable-ldpi/jog_tab_bar_left_end_pressed.9.png
index 95b4f4b..7a98b61 100644
--- a/core/res/res/drawable-ldpi/jog_tab_bar_left_end_pressed.9.png
+++ b/core/res/res/drawable-ldpi/jog_tab_bar_left_end_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_tab_bar_right_end_confirm_gray.9.png b/core/res/res/drawable-ldpi/jog_tab_bar_right_end_confirm_gray.9.png
index 2bec09e..1df750f 100644
--- a/core/res/res/drawable-ldpi/jog_tab_bar_right_end_confirm_gray.9.png
+++ b/core/res/res/drawable-ldpi/jog_tab_bar_right_end_confirm_gray.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_tab_bar_right_end_confirm_green.9.png b/core/res/res/drawable-ldpi/jog_tab_bar_right_end_confirm_green.9.png
index 8f8109e..62714a3 100644
--- a/core/res/res/drawable-ldpi/jog_tab_bar_right_end_confirm_green.9.png
+++ b/core/res/res/drawable-ldpi/jog_tab_bar_right_end_confirm_green.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_tab_bar_right_end_confirm_red.9.png b/core/res/res/drawable-ldpi/jog_tab_bar_right_end_confirm_red.9.png
index a453ac3..32ec24e 100644
--- a/core/res/res/drawable-ldpi/jog_tab_bar_right_end_confirm_red.9.png
+++ b/core/res/res/drawable-ldpi/jog_tab_bar_right_end_confirm_red.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_tab_bar_right_end_confirm_yellow.9.png b/core/res/res/drawable-ldpi/jog_tab_bar_right_end_confirm_yellow.9.png
index f7ef794..30280d1 100644
--- a/core/res/res/drawable-ldpi/jog_tab_bar_right_end_confirm_yellow.9.png
+++ b/core/res/res/drawable-ldpi/jog_tab_bar_right_end_confirm_yellow.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_tab_bar_right_end_normal.9.png b/core/res/res/drawable-ldpi/jog_tab_bar_right_end_normal.9.png
index 74b769b..b70003a 100644
--- a/core/res/res/drawable-ldpi/jog_tab_bar_right_end_normal.9.png
+++ b/core/res/res/drawable-ldpi/jog_tab_bar_right_end_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_tab_bar_right_end_pressed.9.png b/core/res/res/drawable-ldpi/jog_tab_bar_right_end_pressed.9.png
index d12058d..aea9717 100644
--- a/core/res/res/drawable-ldpi/jog_tab_bar_right_end_pressed.9.png
+++ b/core/res/res/drawable-ldpi/jog_tab_bar_right_end_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_tab_left_confirm_gray.png b/core/res/res/drawable-ldpi/jog_tab_left_confirm_gray.png
index 92c4a2e..56acc61 100644
--- a/core/res/res/drawable-ldpi/jog_tab_left_confirm_gray.png
+++ b/core/res/res/drawable-ldpi/jog_tab_left_confirm_gray.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_tab_left_confirm_green.png b/core/res/res/drawable-ldpi/jog_tab_left_confirm_green.png
index 13b7c63..82bc314 100644
--- a/core/res/res/drawable-ldpi/jog_tab_left_confirm_green.png
+++ b/core/res/res/drawable-ldpi/jog_tab_left_confirm_green.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_tab_left_confirm_red.png b/core/res/res/drawable-ldpi/jog_tab_left_confirm_red.png
index 414c07b..f305728 100644
--- a/core/res/res/drawable-ldpi/jog_tab_left_confirm_red.png
+++ b/core/res/res/drawable-ldpi/jog_tab_left_confirm_red.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_tab_left_confirm_yellow.png b/core/res/res/drawable-ldpi/jog_tab_left_confirm_yellow.png
index afccc39..057d350 100644
--- a/core/res/res/drawable-ldpi/jog_tab_left_confirm_yellow.png
+++ b/core/res/res/drawable-ldpi/jog_tab_left_confirm_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_tab_left_normal.png b/core/res/res/drawable-ldpi/jog_tab_left_normal.png
index 6ba6479..a0950183 100644
--- a/core/res/res/drawable-ldpi/jog_tab_left_normal.png
+++ b/core/res/res/drawable-ldpi/jog_tab_left_normal.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_tab_left_pressed.png b/core/res/res/drawable-ldpi/jog_tab_left_pressed.png
index 3dc9c47..a167099 100644
--- a/core/res/res/drawable-ldpi/jog_tab_left_pressed.png
+++ b/core/res/res/drawable-ldpi/jog_tab_left_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_tab_right_confirm_gray.png b/core/res/res/drawable-ldpi/jog_tab_right_confirm_gray.png
index ec1020d..3238ec0b 100644
--- a/core/res/res/drawable-ldpi/jog_tab_right_confirm_gray.png
+++ b/core/res/res/drawable-ldpi/jog_tab_right_confirm_gray.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_tab_right_confirm_green.png b/core/res/res/drawable-ldpi/jog_tab_right_confirm_green.png
index 5b600c9..329a3df 100644
--- a/core/res/res/drawable-ldpi/jog_tab_right_confirm_green.png
+++ b/core/res/res/drawable-ldpi/jog_tab_right_confirm_green.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_tab_right_confirm_red.png b/core/res/res/drawable-ldpi/jog_tab_right_confirm_red.png
index b640578..d55c7ab 100644
--- a/core/res/res/drawable-ldpi/jog_tab_right_confirm_red.png
+++ b/core/res/res/drawable-ldpi/jog_tab_right_confirm_red.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_tab_right_confirm_yellow.png b/core/res/res/drawable-ldpi/jog_tab_right_confirm_yellow.png
index c4490bc..bad85cd 100644
--- a/core/res/res/drawable-ldpi/jog_tab_right_confirm_yellow.png
+++ b/core/res/res/drawable-ldpi/jog_tab_right_confirm_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_tab_right_normal.png b/core/res/res/drawable-ldpi/jog_tab_right_normal.png
index 024d409..8b0f76d 100644
--- a/core/res/res/drawable-ldpi/jog_tab_right_normal.png
+++ b/core/res/res/drawable-ldpi/jog_tab_right_normal.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_tab_right_pressed.png b/core/res/res/drawable-ldpi/jog_tab_right_pressed.png
index 22acd25..633124c 100644
--- a/core/res/res/drawable-ldpi/jog_tab_right_pressed.png
+++ b/core/res/res/drawable-ldpi/jog_tab_right_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_tab_target_gray.png b/core/res/res/drawable-ldpi/jog_tab_target_gray.png
index 7921676..6070c43 100644
--- a/core/res/res/drawable-ldpi/jog_tab_target_gray.png
+++ b/core/res/res/drawable-ldpi/jog_tab_target_gray.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_tab_target_green.png b/core/res/res/drawable-ldpi/jog_tab_target_green.png
index df5c273..48f6a7a 100644
--- a/core/res/res/drawable-ldpi/jog_tab_target_green.png
+++ b/core/res/res/drawable-ldpi/jog_tab_target_green.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_tab_target_red.png b/core/res/res/drawable-ldpi/jog_tab_target_red.png
index 2bb6df9..0806784 100644
--- a/core/res/res/drawable-ldpi/jog_tab_target_red.png
+++ b/core/res/res/drawable-ldpi/jog_tab_target_red.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/jog_tab_target_yellow.png b/core/res/res/drawable-ldpi/jog_tab_target_yellow.png
index e7e4347..8a04f38 100644
--- a/core/res/res/drawable-ldpi/jog_tab_target_yellow.png
+++ b/core/res/res/drawable-ldpi/jog_tab_target_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/keyboard_accessory_bg_landscape.9.png b/core/res/res/drawable-ldpi/keyboard_accessory_bg_landscape.9.png
index 4ab1dd0..83140ec 100644
--- a/core/res/res/drawable-ldpi/keyboard_accessory_bg_landscape.9.png
+++ b/core/res/res/drawable-ldpi/keyboard_accessory_bg_landscape.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/keyboard_background.9.png b/core/res/res/drawable-ldpi/keyboard_background.9.png
index 06d42c0..5cc27ed 100644
--- a/core/res/res/drawable-ldpi/keyboard_background.9.png
+++ b/core/res/res/drawable-ldpi/keyboard_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/keyboard_key_feedback_background.9.png b/core/res/res/drawable-ldpi/keyboard_key_feedback_background.9.png
index 6f936f1..f60da5f 100644
--- a/core/res/res/drawable-ldpi/keyboard_key_feedback_background.9.png
+++ b/core/res/res/drawable-ldpi/keyboard_key_feedback_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/keyboard_key_feedback_more_background.9.png b/core/res/res/drawable-ldpi/keyboard_key_feedback_more_background.9.png
index 7e81c3d4..d4fc87c 100644
--- a/core/res/res/drawable-ldpi/keyboard_key_feedback_more_background.9.png
+++ b/core/res/res/drawable-ldpi/keyboard_key_feedback_more_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/keyboard_popup_panel_background.9.png b/core/res/res/drawable-ldpi/keyboard_popup_panel_background.9.png
index 955fecc..3c5eaf4 100644
--- a/core/res/res/drawable-ldpi/keyboard_popup_panel_background.9.png
+++ b/core/res/res/drawable-ldpi/keyboard_popup_panel_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/keyboard_popup_panel_trans_background.9.png b/core/res/res/drawable-ldpi/keyboard_popup_panel_trans_background.9.png
index 78ac46d..beb36da 100644
--- a/core/res/res/drawable-ldpi/keyboard_popup_panel_trans_background.9.png
+++ b/core/res/res/drawable-ldpi/keyboard_popup_panel_trans_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/light_header.9.png b/core/res/res/drawable-ldpi/light_header.9.png
index 4318252..d3f45c7 100644
--- a/core/res/res/drawable-ldpi/light_header.9.png
+++ b/core/res/res/drawable-ldpi/light_header.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/list_selector_background_disabled.9.png b/core/res/res/drawable-ldpi/list_selector_background_disabled.9.png
index b94396b..44127ee 100644
--- a/core/res/res/drawable-ldpi/list_selector_background_disabled.9.png
+++ b/core/res/res/drawable-ldpi/list_selector_background_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/list_selector_background_focus.9.png b/core/res/res/drawable-ldpi/list_selector_background_focus.9.png
index f2887a9..2a2a0e2 100644
--- a/core/res/res/drawable-ldpi/list_selector_background_focus.9.png
+++ b/core/res/res/drawable-ldpi/list_selector_background_focus.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/list_selector_background_longpress.9.png b/core/res/res/drawable-ldpi/list_selector_background_longpress.9.png
index 1fb46bb..b422d58 100644
--- a/core/res/res/drawable-ldpi/list_selector_background_longpress.9.png
+++ b/core/res/res/drawable-ldpi/list_selector_background_longpress.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/list_selector_background_pressed.9.png b/core/res/res/drawable-ldpi/list_selector_background_pressed.9.png
index 4980eab..bb6ad7b 100644
--- a/core/res/res/drawable-ldpi/list_selector_background_pressed.9.png
+++ b/core/res/res/drawable-ldpi/list_selector_background_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/maps_google_logo.png b/core/res/res/drawable-ldpi/maps_google_logo.png
index 84cc523..bff952b 100644
--- a/core/res/res/drawable-ldpi/maps_google_logo.png
+++ b/core/res/res/drawable-ldpi/maps_google_logo.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/menu_background.9.png b/core/res/res/drawable-ldpi/menu_background.9.png
index 18c1f40..fbd67b5 100644
--- a/core/res/res/drawable-ldpi/menu_background.9.png
+++ b/core/res/res/drawable-ldpi/menu_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/menu_background_fill_parent_width.9.png b/core/res/res/drawable-ldpi/menu_background_fill_parent_width.9.png
index 02de323..d3c422d 100644
--- a/core/res/res/drawable-ldpi/menu_background_fill_parent_width.9.png
+++ b/core/res/res/drawable-ldpi/menu_background_fill_parent_width.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/menu_separator.9.png b/core/res/res/drawable-ldpi/menu_separator.9.png
index 9e2dd7f..bf1c87a 100644
--- a/core/res/res/drawable-ldpi/menu_separator.9.png
+++ b/core/res/res/drawable-ldpi/menu_separator.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/menu_submenu_background.9.png b/core/res/res/drawable-ldpi/menu_submenu_background.9.png
index 25b27d4..52f493d 100644
--- a/core/res/res/drawable-ldpi/menu_submenu_background.9.png
+++ b/core/res/res/drawable-ldpi/menu_submenu_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/menuitem_background_focus.9.png b/core/res/res/drawable-ldpi/menuitem_background_focus.9.png
index 072b665..abd8beb 100644
--- a/core/res/res/drawable-ldpi/menuitem_background_focus.9.png
+++ b/core/res/res/drawable-ldpi/menuitem_background_focus.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/menuitem_background_pressed.9.png b/core/res/res/drawable-ldpi/menuitem_background_pressed.9.png
index 1def2a1..5972f5d 100644
--- a/core/res/res/drawable-ldpi/menuitem_background_pressed.9.png
+++ b/core/res/res/drawable-ldpi/menuitem_background_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/menuitem_background_solid_focused.9.png b/core/res/res/drawable-ldpi/menuitem_background_solid_focused.9.png
index 671e756..533bda8 100644
--- a/core/res/res/drawable-ldpi/menuitem_background_solid_focused.9.png
+++ b/core/res/res/drawable-ldpi/menuitem_background_solid_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/menuitem_background_solid_pressed.9.png b/core/res/res/drawable-ldpi/menuitem_background_solid_pressed.9.png
index 5f334d8..233e108 100644
--- a/core/res/res/drawable-ldpi/menuitem_background_solid_pressed.9.png
+++ b/core/res/res/drawable-ldpi/menuitem_background_solid_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/menuitem_checkbox_on.png b/core/res/res/drawable-ldpi/menuitem_checkbox_on.png
index 61a4843..cd8f529 100644
--- a/core/res/res/drawable-ldpi/menuitem_checkbox_on.png
+++ b/core/res/res/drawable-ldpi/menuitem_checkbox_on.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/numberpicker_down_disabled.9.png b/core/res/res/drawable-ldpi/numberpicker_down_disabled.9.png
index a4c2aba..72d461e 100644
--- a/core/res/res/drawable-ldpi/numberpicker_down_disabled.9.png
+++ b/core/res/res/drawable-ldpi/numberpicker_down_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/numberpicker_down_disabled_focused.9.png b/core/res/res/drawable-ldpi/numberpicker_down_disabled_focused.9.png
index fdbc9d5..1f2880f 100644
--- a/core/res/res/drawable-ldpi/numberpicker_down_disabled_focused.9.png
+++ b/core/res/res/drawable-ldpi/numberpicker_down_disabled_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/numberpicker_down_normal.9.png b/core/res/res/drawable-ldpi/numberpicker_down_normal.9.png
index c7e8018..4852a07 100644
--- a/core/res/res/drawable-ldpi/numberpicker_down_normal.9.png
+++ b/core/res/res/drawable-ldpi/numberpicker_down_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/numberpicker_down_pressed.9.png b/core/res/res/drawable-ldpi/numberpicker_down_pressed.9.png
index 4dd82ae..1f23680 100644
--- a/core/res/res/drawable-ldpi/numberpicker_down_pressed.9.png
+++ b/core/res/res/drawable-ldpi/numberpicker_down_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/numberpicker_down_selected.9.png b/core/res/res/drawable-ldpi/numberpicker_down_selected.9.png
index ebb701e..7754749 100644
--- a/core/res/res/drawable-ldpi/numberpicker_down_selected.9.png
+++ b/core/res/res/drawable-ldpi/numberpicker_down_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/numberpicker_input_disabled.9.png b/core/res/res/drawable-ldpi/numberpicker_input_disabled.9.png
index 39cc3d4..55af416 100644
--- a/core/res/res/drawable-ldpi/numberpicker_input_disabled.9.png
+++ b/core/res/res/drawable-ldpi/numberpicker_input_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/numberpicker_input_normal.9.png b/core/res/res/drawable-ldpi/numberpicker_input_normal.9.png
index 6ffabe6..dd29c95 100644
--- a/core/res/res/drawable-ldpi/numberpicker_input_normal.9.png
+++ b/core/res/res/drawable-ldpi/numberpicker_input_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/numberpicker_input_pressed.9.png b/core/res/res/drawable-ldpi/numberpicker_input_pressed.9.png
index 9cfaaab..d84128f 100644
--- a/core/res/res/drawable-ldpi/numberpicker_input_pressed.9.png
+++ b/core/res/res/drawable-ldpi/numberpicker_input_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/numberpicker_input_selected.9.png b/core/res/res/drawable-ldpi/numberpicker_input_selected.9.png
index e819e9b..e7cddd7 100644
--- a/core/res/res/drawable-ldpi/numberpicker_input_selected.9.png
+++ b/core/res/res/drawable-ldpi/numberpicker_input_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/numberpicker_up_disabled.9.png b/core/res/res/drawable-ldpi/numberpicker_up_disabled.9.png
index 005a5ae..dc2e6d0 100644
--- a/core/res/res/drawable-ldpi/numberpicker_up_disabled.9.png
+++ b/core/res/res/drawable-ldpi/numberpicker_up_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/numberpicker_up_disabled_focused.9.png b/core/res/res/drawable-ldpi/numberpicker_up_disabled_focused.9.png
index f1c9465..839d16f 100644
--- a/core/res/res/drawable-ldpi/numberpicker_up_disabled_focused.9.png
+++ b/core/res/res/drawable-ldpi/numberpicker_up_disabled_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/numberpicker_up_normal.9.png b/core/res/res/drawable-ldpi/numberpicker_up_normal.9.png
index 9927539..37221be 100644
--- a/core/res/res/drawable-ldpi/numberpicker_up_normal.9.png
+++ b/core/res/res/drawable-ldpi/numberpicker_up_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/numberpicker_up_pressed.9.png b/core/res/res/drawable-ldpi/numberpicker_up_pressed.9.png
index 7946450..c5ed2d6b 100644
--- a/core/res/res/drawable-ldpi/numberpicker_up_pressed.9.png
+++ b/core/res/res/drawable-ldpi/numberpicker_up_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/numberpicker_up_selected.9.png b/core/res/res/drawable-ldpi/numberpicker_up_selected.9.png
index 8c8136a..15aaf78 100644
--- a/core/res/res/drawable-ldpi/numberpicker_up_selected.9.png
+++ b/core/res/res/drawable-ldpi/numberpicker_up_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/panel_background.9.png b/core/res/res/drawable-ldpi/panel_background.9.png
index 7ea328d..d279e00 100644
--- a/core/res/res/drawable-ldpi/panel_background.9.png
+++ b/core/res/res/drawable-ldpi/panel_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/panel_picture_frame_bg_focus_blue.9.png b/core/res/res/drawable-ldpi/panel_picture_frame_bg_focus_blue.9.png
index 14eb7f7..47b7d97 100644
--- a/core/res/res/drawable-ldpi/panel_picture_frame_bg_focus_blue.9.png
+++ b/core/res/res/drawable-ldpi/panel_picture_frame_bg_focus_blue.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/panel_picture_frame_bg_normal.9.png b/core/res/res/drawable-ldpi/panel_picture_frame_bg_normal.9.png
index c8cd101..a54ac3e 100644
--- a/core/res/res/drawable-ldpi/panel_picture_frame_bg_normal.9.png
+++ b/core/res/res/drawable-ldpi/panel_picture_frame_bg_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/panel_picture_frame_bg_pressed_blue.9.png b/core/res/res/drawable-ldpi/panel_picture_frame_bg_pressed_blue.9.png
index 0badf2b..e52b3d7 100644
--- a/core/res/res/drawable-ldpi/panel_picture_frame_bg_pressed_blue.9.png
+++ b/core/res/res/drawable-ldpi/panel_picture_frame_bg_pressed_blue.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/password_field_default.9.png b/core/res/res/drawable-ldpi/password_field_default.9.png
index a84abf2..39f225d 100644
--- a/core/res/res/drawable-ldpi/password_field_default.9.png
+++ b/core/res/res/drawable-ldpi/password_field_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/picture_emergency.png b/core/res/res/drawable-ldpi/picture_emergency.png
index dbb738f9..d8f248b 100644
--- a/core/res/res/drawable-ldpi/picture_emergency.png
+++ b/core/res/res/drawable-ldpi/picture_emergency.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/picture_frame.9.png b/core/res/res/drawable-ldpi/picture_frame.9.png
index f302bf3..03bfa3b 100644
--- a/core/res/res/drawable-ldpi/picture_frame.9.png
+++ b/core/res/res/drawable-ldpi/picture_frame.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/popup_bottom_bright.9.png b/core/res/res/drawable-ldpi/popup_bottom_bright.9.png
index a8d52a2..9ffb35d 100644
--- a/core/res/res/drawable-ldpi/popup_bottom_bright.9.png
+++ b/core/res/res/drawable-ldpi/popup_bottom_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/popup_bottom_dark.9.png b/core/res/res/drawable-ldpi/popup_bottom_dark.9.png
index b0b64df..0638fed2 100644
--- a/core/res/res/drawable-ldpi/popup_bottom_dark.9.png
+++ b/core/res/res/drawable-ldpi/popup_bottom_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/popup_bottom_medium.9.png b/core/res/res/drawable-ldpi/popup_bottom_medium.9.png
index 7bdef97..b385141 100644
--- a/core/res/res/drawable-ldpi/popup_bottom_medium.9.png
+++ b/core/res/res/drawable-ldpi/popup_bottom_medium.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/popup_center_bright.9.png b/core/res/res/drawable-ldpi/popup_center_bright.9.png
index 0bfe6ba..a4421fa 100644
--- a/core/res/res/drawable-ldpi/popup_center_bright.9.png
+++ b/core/res/res/drawable-ldpi/popup_center_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/popup_center_dark.9.png b/core/res/res/drawable-ldpi/popup_center_dark.9.png
index e76a452..0bc3075 100644
--- a/core/res/res/drawable-ldpi/popup_center_dark.9.png
+++ b/core/res/res/drawable-ldpi/popup_center_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/popup_center_medium.9.png b/core/res/res/drawable-ldpi/popup_center_medium.9.png
index a8de187..2c87dd3 100644
--- a/core/res/res/drawable-ldpi/popup_center_medium.9.png
+++ b/core/res/res/drawable-ldpi/popup_center_medium.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/popup_full_bright.9.png b/core/res/res/drawable-ldpi/popup_full_bright.9.png
index b6bbacd..d54449a 100644
--- a/core/res/res/drawable-ldpi/popup_full_bright.9.png
+++ b/core/res/res/drawable-ldpi/popup_full_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/popup_full_dark.9.png b/core/res/res/drawable-ldpi/popup_full_dark.9.png
index ed36fce..0ef5a20 100644
--- a/core/res/res/drawable-ldpi/popup_full_dark.9.png
+++ b/core/res/res/drawable-ldpi/popup_full_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/popup_inline_error_above_am.9.png b/core/res/res/drawable-ldpi/popup_inline_error_above_am.9.png
index 673685d..39cd31c 100644
--- a/core/res/res/drawable-ldpi/popup_inline_error_above_am.9.png
+++ b/core/res/res/drawable-ldpi/popup_inline_error_above_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/popup_inline_error_am.9.png b/core/res/res/drawable-ldpi/popup_inline_error_am.9.png
index cdc66ff..9fb6bf6 100644
--- a/core/res/res/drawable-ldpi/popup_inline_error_am.9.png
+++ b/core/res/res/drawable-ldpi/popup_inline_error_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/popup_top_bright.9.png b/core/res/res/drawable-ldpi/popup_top_bright.9.png
index 51f1f0f..5799631 100644
--- a/core/res/res/drawable-ldpi/popup_top_bright.9.png
+++ b/core/res/res/drawable-ldpi/popup_top_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/popup_top_dark.9.png b/core/res/res/drawable-ldpi/popup_top_dark.9.png
index 81e1918..0c64254 100644
--- a/core/res/res/drawable-ldpi/popup_top_dark.9.png
+++ b/core/res/res/drawable-ldpi/popup_top_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/presence_audio_away.png b/core/res/res/drawable-ldpi/presence_audio_away.png
index 73ad0da..7023e19 100644
--- a/core/res/res/drawable-ldpi/presence_audio_away.png
+++ b/core/res/res/drawable-ldpi/presence_audio_away.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/presence_audio_busy.png b/core/res/res/drawable-ldpi/presence_audio_busy.png
index 8b64d45..ba1328c 100644
--- a/core/res/res/drawable-ldpi/presence_audio_busy.png
+++ b/core/res/res/drawable-ldpi/presence_audio_busy.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/presence_audio_online.png b/core/res/res/drawable-ldpi/presence_audio_online.png
index 455db0528..94feb54 100644
--- a/core/res/res/drawable-ldpi/presence_audio_online.png
+++ b/core/res/res/drawable-ldpi/presence_audio_online.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/presence_away.png b/core/res/res/drawable-ldpi/presence_away.png
index 5228a4b..507ba02 100644
--- a/core/res/res/drawable-ldpi/presence_away.png
+++ b/core/res/res/drawable-ldpi/presence_away.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/presence_busy.png b/core/res/res/drawable-ldpi/presence_busy.png
index 79fddf7..274b87a 100644
--- a/core/res/res/drawable-ldpi/presence_busy.png
+++ b/core/res/res/drawable-ldpi/presence_busy.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/presence_invisible.png b/core/res/res/drawable-ldpi/presence_invisible.png
index fb1654b..6db7184 100644
--- a/core/res/res/drawable-ldpi/presence_invisible.png
+++ b/core/res/res/drawable-ldpi/presence_invisible.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/presence_offline.png b/core/res/res/drawable-ldpi/presence_offline.png
index 4546799..5e419ee 100644
--- a/core/res/res/drawable-ldpi/presence_offline.png
+++ b/core/res/res/drawable-ldpi/presence_offline.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/presence_online.png b/core/res/res/drawable-ldpi/presence_online.png
index c400a18..5fff25f 100644
--- a/core/res/res/drawable-ldpi/presence_online.png
+++ b/core/res/res/drawable-ldpi/presence_online.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/presence_video_away.png b/core/res/res/drawable-ldpi/presence_video_away.png
index 3695a0e..52d639a 100644
--- a/core/res/res/drawable-ldpi/presence_video_away.png
+++ b/core/res/res/drawable-ldpi/presence_video_away.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/presence_video_busy.png b/core/res/res/drawable-ldpi/presence_video_busy.png
index c4b0728..c5b8609 100644
--- a/core/res/res/drawable-ldpi/presence_video_busy.png
+++ b/core/res/res/drawable-ldpi/presence_video_busy.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/presence_video_online.png b/core/res/res/drawable-ldpi/presence_video_online.png
index 786d0e6..57c9610 100644
--- a/core/res/res/drawable-ldpi/presence_video_online.png
+++ b/core/res/res/drawable-ldpi/presence_video_online.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/pressed_application_background_static.png b/core/res/res/drawable-ldpi/pressed_application_background_static.png
index d0fd302..995199e 100644
--- a/core/res/res/drawable-ldpi/pressed_application_background_static.png
+++ b/core/res/res/drawable-ldpi/pressed_application_background_static.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/progressbar_indeterminate1.png b/core/res/res/drawable-ldpi/progressbar_indeterminate1.png
index 92a1aee..4fe1c20 100644
--- a/core/res/res/drawable-ldpi/progressbar_indeterminate1.png
+++ b/core/res/res/drawable-ldpi/progressbar_indeterminate1.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/progressbar_indeterminate2.png b/core/res/res/drawable-ldpi/progressbar_indeterminate2.png
index 1fd2f37..156da8b 100644
--- a/core/res/res/drawable-ldpi/progressbar_indeterminate2.png
+++ b/core/res/res/drawable-ldpi/progressbar_indeterminate2.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/progressbar_indeterminate3.png b/core/res/res/drawable-ldpi/progressbar_indeterminate3.png
index adb8022..c4a6e40 100644
--- a/core/res/res/drawable-ldpi/progressbar_indeterminate3.png
+++ b/core/res/res/drawable-ldpi/progressbar_indeterminate3.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/radiobutton_off_background.png b/core/res/res/drawable-ldpi/radiobutton_off_background.png
index d8023c9..3cec339 100644
--- a/core/res/res/drawable-ldpi/radiobutton_off_background.png
+++ b/core/res/res/drawable-ldpi/radiobutton_off_background.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/radiobutton_on_background.png b/core/res/res/drawable-ldpi/radiobutton_on_background.png
index 4014d4b..0bc6a0e 100644
--- a/core/res/res/drawable-ldpi/radiobutton_on_background.png
+++ b/core/res/res/drawable-ldpi/radiobutton_on_background.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/rate_star_big_half.png b/core/res/res/drawable-ldpi/rate_star_big_half.png
index 0b4dc17..24509de 100644
--- a/core/res/res/drawable-ldpi/rate_star_big_half.png
+++ b/core/res/res/drawable-ldpi/rate_star_big_half.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/rate_star_big_off.png b/core/res/res/drawable-ldpi/rate_star_big_off.png
index 1d8eef6..eb45bf5 100644
--- a/core/res/res/drawable-ldpi/rate_star_big_off.png
+++ b/core/res/res/drawable-ldpi/rate_star_big_off.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/rate_star_big_on.png b/core/res/res/drawable-ldpi/rate_star_big_on.png
index b6d4d89..56236d9 100644
--- a/core/res/res/drawable-ldpi/rate_star_big_on.png
+++ b/core/res/res/drawable-ldpi/rate_star_big_on.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/rate_star_med_half.png b/core/res/res/drawable-ldpi/rate_star_med_half.png
index f9bcc5c..952e3a2 100644
--- a/core/res/res/drawable-ldpi/rate_star_med_half.png
+++ b/core/res/res/drawable-ldpi/rate_star_med_half.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/rate_star_med_off.png b/core/res/res/drawable-ldpi/rate_star_med_off.png
index eec4ae5..f295339 100644
--- a/core/res/res/drawable-ldpi/rate_star_med_off.png
+++ b/core/res/res/drawable-ldpi/rate_star_med_off.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/rate_star_med_on.png b/core/res/res/drawable-ldpi/rate_star_med_on.png
index 03a4cff..91318c5 100644
--- a/core/res/res/drawable-ldpi/rate_star_med_on.png
+++ b/core/res/res/drawable-ldpi/rate_star_med_on.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/rate_star_small_half.png b/core/res/res/drawable-ldpi/rate_star_small_half.png
index 3e2b99b..686af83 100644
--- a/core/res/res/drawable-ldpi/rate_star_small_half.png
+++ b/core/res/res/drawable-ldpi/rate_star_small_half.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/rate_star_small_off.png b/core/res/res/drawable-ldpi/rate_star_small_off.png
index 19db372..dddbb5a 100644
--- a/core/res/res/drawable-ldpi/rate_star_small_off.png
+++ b/core/res/res/drawable-ldpi/rate_star_small_off.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/rate_star_small_on.png b/core/res/res/drawable-ldpi/rate_star_small_on.png
index b3b9a84..944732c 100644
--- a/core/res/res/drawable-ldpi/rate_star_small_on.png
+++ b/core/res/res/drawable-ldpi/rate_star_small_on.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/recent_dialog_background.9.png b/core/res/res/drawable-ldpi/recent_dialog_background.9.png
index ab8d87d..0b232d5 100644
--- a/core/res/res/drawable-ldpi/recent_dialog_background.9.png
+++ b/core/res/res/drawable-ldpi/recent_dialog_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/reticle.png b/core/res/res/drawable-ldpi/reticle.png
index daaee11..2b3563a 100644
--- a/core/res/res/drawable-ldpi/reticle.png
+++ b/core/res/res/drawable-ldpi/reticle.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/scrollbar_handle_accelerated_anim2.9.png b/core/res/res/drawable-ldpi/scrollbar_handle_accelerated_anim2.9.png
index a4ca3e0..36f3cfc 100644
--- a/core/res/res/drawable-ldpi/scrollbar_handle_accelerated_anim2.9.png
+++ b/core/res/res/drawable-ldpi/scrollbar_handle_accelerated_anim2.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/scrollbar_handle_horizontal.9.png b/core/res/res/drawable-ldpi/scrollbar_handle_horizontal.9.png
index b3c10cf..88d3fce 100644
--- a/core/res/res/drawable-ldpi/scrollbar_handle_horizontal.9.png
+++ b/core/res/res/drawable-ldpi/scrollbar_handle_horizontal.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/scrollbar_handle_vertical.9.png b/core/res/res/drawable-ldpi/scrollbar_handle_vertical.9.png
index a04e632..a832100 100644
--- a/core/res/res/drawable-ldpi/scrollbar_handle_vertical.9.png
+++ b/core/res/res/drawable-ldpi/scrollbar_handle_vertical.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/search_dropdown_background.9.png b/core/res/res/drawable-ldpi/search_dropdown_background.9.png
index b695dcb..5a0f4a2 100644
--- a/core/res/res/drawable-ldpi/search_dropdown_background.9.png
+++ b/core/res/res/drawable-ldpi/search_dropdown_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/search_plate.9.png b/core/res/res/drawable-ldpi/search_plate.9.png
index 40a351f..c86c11d 100644
--- a/core/res/res/drawable-ldpi/search_plate.9.png
+++ b/core/res/res/drawable-ldpi/search_plate.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/search_plate_global.9.png b/core/res/res/drawable-ldpi/search_plate_global.9.png
index 2fa2129..498fd86 100644
--- a/core/res/res/drawable-ldpi/search_plate_global.9.png
+++ b/core/res/res/drawable-ldpi/search_plate_global.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/seek_thumb_normal.png b/core/res/res/drawable-ldpi/seek_thumb_normal.png
index 9c2d90d..3d6abdf 100644
--- a/core/res/res/drawable-ldpi/seek_thumb_normal.png
+++ b/core/res/res/drawable-ldpi/seek_thumb_normal.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/seek_thumb_pressed.png b/core/res/res/drawable-ldpi/seek_thumb_pressed.png
index 555cde8..cac84b1 100644
--- a/core/res/res/drawable-ldpi/seek_thumb_pressed.png
+++ b/core/res/res/drawable-ldpi/seek_thumb_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/seek_thumb_selected.png b/core/res/res/drawable-ldpi/seek_thumb_selected.png
index 4f11818..bcd8d36 100644
--- a/core/res/res/drawable-ldpi/seek_thumb_selected.png
+++ b/core/res/res/drawable-ldpi/seek_thumb_selected.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/settings_header_raw.9.png b/core/res/res/drawable-ldpi/settings_header_raw.9.png
index 142d8c2..74f295a 100644
--- a/core/res/res/drawable-ldpi/settings_header_raw.9.png
+++ b/core/res/res/drawable-ldpi/settings_header_raw.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/spinner_black_16.png b/core/res/res/drawable-ldpi/spinner_black_16.png
index c876d8a..d4e717a 100644
--- a/core/res/res/drawable-ldpi/spinner_black_16.png
+++ b/core/res/res/drawable-ldpi/spinner_black_16.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/spinner_black_20.png b/core/res/res/drawable-ldpi/spinner_black_20.png
index 7751f9a..954dcbc 100644
--- a/core/res/res/drawable-ldpi/spinner_black_20.png
+++ b/core/res/res/drawable-ldpi/spinner_black_20.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/spinner_black_48.png b/core/res/res/drawable-ldpi/spinner_black_48.png
index c7aa517..1407878 100644
--- a/core/res/res/drawable-ldpi/spinner_black_48.png
+++ b/core/res/res/drawable-ldpi/spinner_black_48.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/spinner_black_76.png b/core/res/res/drawable-ldpi/spinner_black_76.png
index 44f559c..64bbc03 100644
--- a/core/res/res/drawable-ldpi/spinner_black_76.png
+++ b/core/res/res/drawable-ldpi/spinner_black_76.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/spinner_dropdown_background_down.9.png b/core/res/res/drawable-ldpi/spinner_dropdown_background_down.9.png
index f9c4610..ad2bb70 100644
--- a/core/res/res/drawable-ldpi/spinner_dropdown_background_down.9.png
+++ b/core/res/res/drawable-ldpi/spinner_dropdown_background_down.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/spinner_dropdown_background_up.9.png b/core/res/res/drawable-ldpi/spinner_dropdown_background_up.9.png
index f458ad4..a64b00a 100644
--- a/core/res/res/drawable-ldpi/spinner_dropdown_background_up.9.png
+++ b/core/res/res/drawable-ldpi/spinner_dropdown_background_up.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/spinner_normal.9.png b/core/res/res/drawable-ldpi/spinner_normal.9.png
index 151c2e6..ced2091 100644
--- a/core/res/res/drawable-ldpi/spinner_normal.9.png
+++ b/core/res/res/drawable-ldpi/spinner_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/spinner_press.9.png b/core/res/res/drawable-ldpi/spinner_press.9.png
index f3be1fc..4e87db5 100644
--- a/core/res/res/drawable-ldpi/spinner_press.9.png
+++ b/core/res/res/drawable-ldpi/spinner_press.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/spinner_select.9.png b/core/res/res/drawable-ldpi/spinner_select.9.png
index 092168b..744576e 100644
--- a/core/res/res/drawable-ldpi/spinner_select.9.png
+++ b/core/res/res/drawable-ldpi/spinner_select.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/spinner_white_16.png b/core/res/res/drawable-ldpi/spinner_white_16.png
index 0ad9eb0..64fdc95 100644
--- a/core/res/res/drawable-ldpi/spinner_white_16.png
+++ b/core/res/res/drawable-ldpi/spinner_white_16.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/spinner_white_48.png b/core/res/res/drawable-ldpi/spinner_white_48.png
index f0f0827..878d2fb 100644
--- a/core/res/res/drawable-ldpi/spinner_white_48.png
+++ b/core/res/res/drawable-ldpi/spinner_white_48.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/spinner_white_76.png b/core/res/res/drawable-ldpi/spinner_white_76.png
index 8be8f26..1aa89c2 100644
--- a/core/res/res/drawable-ldpi/spinner_white_76.png
+++ b/core/res/res/drawable-ldpi/spinner_white_76.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/star_big_off.png b/core/res/res/drawable-ldpi/star_big_off.png
index d91c3a4..3b54c3a 100644
--- a/core/res/res/drawable-ldpi/star_big_off.png
+++ b/core/res/res/drawable-ldpi/star_big_off.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/star_big_on.png b/core/res/res/drawable-ldpi/star_big_on.png
index 69d92a2..2af4be2 100644
--- a/core/res/res/drawable-ldpi/star_big_on.png
+++ b/core/res/res/drawable-ldpi/star_big_on.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/star_off.png b/core/res/res/drawable-ldpi/star_off.png
index 6bc28fc..e12102b 100644
--- a/core/res/res/drawable-ldpi/star_off.png
+++ b/core/res/res/drawable-ldpi/star_off.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/star_on.png b/core/res/res/drawable-ldpi/star_on.png
index d2e3845..4533d84 100644
--- a/core/res/res/drawable-ldpi/star_on.png
+++ b/core/res/res/drawable-ldpi/star_on.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_ecb_mode.png b/core/res/res/drawable-ldpi/stat_ecb_mode.png
index a17d7db..91a4cbb 100644
--- a/core/res/res/drawable-ldpi/stat_ecb_mode.png
+++ b/core/res/res/drawable-ldpi/stat_ecb_mode.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_notify_car_mode.png b/core/res/res/drawable-ldpi/stat_notify_car_mode.png
index 22e90aef..5b3bf23 100644
--- a/core/res/res/drawable-ldpi/stat_notify_car_mode.png
+++ b/core/res/res/drawable-ldpi/stat_notify_car_mode.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_notify_chat.png b/core/res/res/drawable-ldpi/stat_notify_chat.png
index 562fbcc..21c90a9 100644
--- a/core/res/res/drawable-ldpi/stat_notify_chat.png
+++ b/core/res/res/drawable-ldpi/stat_notify_chat.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_notify_disk_full.png b/core/res/res/drawable-ldpi/stat_notify_disk_full.png
index c329486..fd95ff1 100644
--- a/core/res/res/drawable-ldpi/stat_notify_disk_full.png
+++ b/core/res/res/drawable-ldpi/stat_notify_disk_full.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_notify_email_generic.png b/core/res/res/drawable-ldpi/stat_notify_email_generic.png
index 352267c..f24a186 100644
--- a/core/res/res/drawable-ldpi/stat_notify_email_generic.png
+++ b/core/res/res/drawable-ldpi/stat_notify_email_generic.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_notify_error.png b/core/res/res/drawable-ldpi/stat_notify_error.png
index a2eab9b..2b45c1b 100644
--- a/core/res/res/drawable-ldpi/stat_notify_error.png
+++ b/core/res/res/drawable-ldpi/stat_notify_error.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_notify_gmail.png b/core/res/res/drawable-ldpi/stat_notify_gmail.png
index 8fbfd00..f45d9e3 100644
--- a/core/res/res/drawable-ldpi/stat_notify_gmail.png
+++ b/core/res/res/drawable-ldpi/stat_notify_gmail.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_notify_missed_call.png b/core/res/res/drawable-ldpi/stat_notify_missed_call.png
index 4c01206..7f10167 100644
--- a/core/res/res/drawable-ldpi/stat_notify_missed_call.png
+++ b/core/res/res/drawable-ldpi/stat_notify_missed_call.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_notify_more.png b/core/res/res/drawable-ldpi/stat_notify_more.png
index a51341d..18f4a6e 100644
--- a/core/res/res/drawable-ldpi/stat_notify_more.png
+++ b/core/res/res/drawable-ldpi/stat_notify_more.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_notify_sdcard.png b/core/res/res/drawable-ldpi/stat_notify_sdcard.png
index 265fd8f..626685a 100644
--- a/core/res/res/drawable-ldpi/stat_notify_sdcard.png
+++ b/core/res/res/drawable-ldpi/stat_notify_sdcard.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_notify_sdcard_prepare.png b/core/res/res/drawable-ldpi/stat_notify_sdcard_prepare.png
index 84cb224..924fd15 100644
--- a/core/res/res/drawable-ldpi/stat_notify_sdcard_prepare.png
+++ b/core/res/res/drawable-ldpi/stat_notify_sdcard_prepare.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_notify_sdcard_usb.png b/core/res/res/drawable-ldpi/stat_notify_sdcard_usb.png
index cb7022b..6ca94bd 100644
--- a/core/res/res/drawable-ldpi/stat_notify_sdcard_usb.png
+++ b/core/res/res/drawable-ldpi/stat_notify_sdcard_usb.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_notify_sim_toolkit.png b/core/res/res/drawable-ldpi/stat_notify_sim_toolkit.png
index d9a62a9..170f6d1 100644
--- a/core/res/res/drawable-ldpi/stat_notify_sim_toolkit.png
+++ b/core/res/res/drawable-ldpi/stat_notify_sim_toolkit.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_notify_sync.png b/core/res/res/drawable-ldpi/stat_notify_sync.png
index dd63030..e803df12 100644
--- a/core/res/res/drawable-ldpi/stat_notify_sync.png
+++ b/core/res/res/drawable-ldpi/stat_notify_sync.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_notify_sync_anim0.png b/core/res/res/drawable-ldpi/stat_notify_sync_anim0.png
index 9aa4edf..b2c4135 100644
--- a/core/res/res/drawable-ldpi/stat_notify_sync_anim0.png
+++ b/core/res/res/drawable-ldpi/stat_notify_sync_anim0.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_notify_sync_error.png b/core/res/res/drawable-ldpi/stat_notify_sync_error.png
index 431a86f..c1a46d6 100644
--- a/core/res/res/drawable-ldpi/stat_notify_sync_error.png
+++ b/core/res/res/drawable-ldpi/stat_notify_sync_error.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_notify_voicemail.png b/core/res/res/drawable-ldpi/stat_notify_voicemail.png
index 36d61a4..af89585 100644
--- a/core/res/res/drawable-ldpi/stat_notify_voicemail.png
+++ b/core/res/res/drawable-ldpi/stat_notify_voicemail.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_battery_0.png b/core/res/res/drawable-ldpi/stat_sys_battery_0.png
index b692c7a..cb27e07 100644
--- a/core/res/res/drawable-ldpi/stat_sys_battery_0.png
+++ b/core/res/res/drawable-ldpi/stat_sys_battery_0.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_battery_10.png b/core/res/res/drawable-ldpi/stat_sys_battery_10.png
index 5e7efd1..31cb6a2 100644
--- a/core/res/res/drawable-ldpi/stat_sys_battery_10.png
+++ b/core/res/res/drawable-ldpi/stat_sys_battery_10.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_battery_100.png b/core/res/res/drawable-ldpi/stat_sys_battery_100.png
index 7023ea7..97fb5df 100644
--- a/core/res/res/drawable-ldpi/stat_sys_battery_100.png
+++ b/core/res/res/drawable-ldpi/stat_sys_battery_100.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_battery_20.png b/core/res/res/drawable-ldpi/stat_sys_battery_20.png
index 275ebbb..d914b0a 100644
--- a/core/res/res/drawable-ldpi/stat_sys_battery_20.png
+++ b/core/res/res/drawable-ldpi/stat_sys_battery_20.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_battery_40.png b/core/res/res/drawable-ldpi/stat_sys_battery_40.png
index 6a46fe0..4c43dac 100644
--- a/core/res/res/drawable-ldpi/stat_sys_battery_40.png
+++ b/core/res/res/drawable-ldpi/stat_sys_battery_40.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_battery_60.png b/core/res/res/drawable-ldpi/stat_sys_battery_60.png
index f94115a..956f73c 100644
--- a/core/res/res/drawable-ldpi/stat_sys_battery_60.png
+++ b/core/res/res/drawable-ldpi/stat_sys_battery_60.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_battery_80.png b/core/res/res/drawable-ldpi/stat_sys_battery_80.png
index 8b07df9..eeece3c 100644
--- a/core/res/res/drawable-ldpi/stat_sys_battery_80.png
+++ b/core/res/res/drawable-ldpi/stat_sys_battery_80.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_battery_charge_anim0.png b/core/res/res/drawable-ldpi/stat_sys_battery_charge_anim0.png
index 7c4a783..a7bb893 100644
--- a/core/res/res/drawable-ldpi/stat_sys_battery_charge_anim0.png
+++ b/core/res/res/drawable-ldpi/stat_sys_battery_charge_anim0.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_battery_charge_anim1.png b/core/res/res/drawable-ldpi/stat_sys_battery_charge_anim1.png
index 9eea8ae..7bcd1d5 100644
--- a/core/res/res/drawable-ldpi/stat_sys_battery_charge_anim1.png
+++ b/core/res/res/drawable-ldpi/stat_sys_battery_charge_anim1.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_battery_charge_anim2.png b/core/res/res/drawable-ldpi/stat_sys_battery_charge_anim2.png
index 112c869..a99d341 100644
--- a/core/res/res/drawable-ldpi/stat_sys_battery_charge_anim2.png
+++ b/core/res/res/drawable-ldpi/stat_sys_battery_charge_anim2.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_battery_charge_anim3.png b/core/res/res/drawable-ldpi/stat_sys_battery_charge_anim3.png
index 7b5c08b..4ec68f3 100644
--- a/core/res/res/drawable-ldpi/stat_sys_battery_charge_anim3.png
+++ b/core/res/res/drawable-ldpi/stat_sys_battery_charge_anim3.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_battery_charge_anim4.png b/core/res/res/drawable-ldpi/stat_sys_battery_charge_anim4.png
index ddda4ad..7d92ec7 100644
--- a/core/res/res/drawable-ldpi/stat_sys_battery_charge_anim4.png
+++ b/core/res/res/drawable-ldpi/stat_sys_battery_charge_anim4.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_battery_charge_anim5.png b/core/res/res/drawable-ldpi/stat_sys_battery_charge_anim5.png
index 52050b2..d888bac 100644
--- a/core/res/res/drawable-ldpi/stat_sys_battery_charge_anim5.png
+++ b/core/res/res/drawable-ldpi/stat_sys_battery_charge_anim5.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_battery_unknown.png b/core/res/res/drawable-ldpi/stat_sys_battery_unknown.png
index e095aa4..8d256e5 100644
--- a/core/res/res/drawable-ldpi/stat_sys_battery_unknown.png
+++ b/core/res/res/drawable-ldpi/stat_sys_battery_unknown.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_data_bluetooth.png b/core/res/res/drawable-ldpi/stat_sys_data_bluetooth.png
index 2ae3355..3e69760 100644
--- a/core/res/res/drawable-ldpi/stat_sys_data_bluetooth.png
+++ b/core/res/res/drawable-ldpi/stat_sys_data_bluetooth.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_data_usb.png b/core/res/res/drawable-ldpi/stat_sys_data_usb.png
index ffaccbd..dbf5321 100644
--- a/core/res/res/drawable-ldpi/stat_sys_data_usb.png
+++ b/core/res/res/drawable-ldpi/stat_sys_data_usb.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_download_anim0.png b/core/res/res/drawable-ldpi/stat_sys_download_anim0.png
index 12c0e21..00b820a 100644
--- a/core/res/res/drawable-ldpi/stat_sys_download_anim0.png
+++ b/core/res/res/drawable-ldpi/stat_sys_download_anim0.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_download_anim1.png b/core/res/res/drawable-ldpi/stat_sys_download_anim1.png
index f5ec4ac..f97eb5f 100644
--- a/core/res/res/drawable-ldpi/stat_sys_download_anim1.png
+++ b/core/res/res/drawable-ldpi/stat_sys_download_anim1.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_download_anim2.png b/core/res/res/drawable-ldpi/stat_sys_download_anim2.png
index 4900ebd..e2d12b6 100644
--- a/core/res/res/drawable-ldpi/stat_sys_download_anim2.png
+++ b/core/res/res/drawable-ldpi/stat_sys_download_anim2.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_download_anim3.png b/core/res/res/drawable-ldpi/stat_sys_download_anim3.png
index aff9ebd..43e762e 100644
--- a/core/res/res/drawable-ldpi/stat_sys_download_anim3.png
+++ b/core/res/res/drawable-ldpi/stat_sys_download_anim3.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_download_anim4.png b/core/res/res/drawable-ldpi/stat_sys_download_anim4.png
index 2eb65db..82f4ca9 100644
--- a/core/res/res/drawable-ldpi/stat_sys_download_anim4.png
+++ b/core/res/res/drawable-ldpi/stat_sys_download_anim4.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_download_anim5.png b/core/res/res/drawable-ldpi/stat_sys_download_anim5.png
index a9f2448..cc25508 100644
--- a/core/res/res/drawable-ldpi/stat_sys_download_anim5.png
+++ b/core/res/res/drawable-ldpi/stat_sys_download_anim5.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_gps_on.png b/core/res/res/drawable-ldpi/stat_sys_gps_on.png
index 77776f5..360b929 100644
--- a/core/res/res/drawable-ldpi/stat_sys_gps_on.png
+++ b/core/res/res/drawable-ldpi/stat_sys_gps_on.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_headset.png b/core/res/res/drawable-ldpi/stat_sys_headset.png
index 8f143a3..ccae652 100644
--- a/core/res/res/drawable-ldpi/stat_sys_headset.png
+++ b/core/res/res/drawable-ldpi/stat_sys_headset.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_phone_call.png b/core/res/res/drawable-ldpi/stat_sys_phone_call.png
index 275bef2..7e0469e 100644
--- a/core/res/res/drawable-ldpi/stat_sys_phone_call.png
+++ b/core/res/res/drawable-ldpi/stat_sys_phone_call.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_phone_call_forward.png b/core/res/res/drawable-ldpi/stat_sys_phone_call_forward.png
index bb07c69..fd09257 100644
--- a/core/res/res/drawable-ldpi/stat_sys_phone_call_forward.png
+++ b/core/res/res/drawable-ldpi/stat_sys_phone_call_forward.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_phone_call_on_hold.png b/core/res/res/drawable-ldpi/stat_sys_phone_call_on_hold.png
index b03816a..f6c76ef 100644
--- a/core/res/res/drawable-ldpi/stat_sys_phone_call_on_hold.png
+++ b/core/res/res/drawable-ldpi/stat_sys_phone_call_on_hold.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_r_signal_0_cdma.png b/core/res/res/drawable-ldpi/stat_sys_r_signal_0_cdma.png
index 2c4ff06..86f085b 100644
--- a/core/res/res/drawable-ldpi/stat_sys_r_signal_0_cdma.png
+++ b/core/res/res/drawable-ldpi/stat_sys_r_signal_0_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_r_signal_1_cdma.png b/core/res/res/drawable-ldpi/stat_sys_r_signal_1_cdma.png
index 82626ac1..6a6201e 100644
--- a/core/res/res/drawable-ldpi/stat_sys_r_signal_1_cdma.png
+++ b/core/res/res/drawable-ldpi/stat_sys_r_signal_1_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_r_signal_2_cdma.png b/core/res/res/drawable-ldpi/stat_sys_r_signal_2_cdma.png
index 96304b1..670710d 100644
--- a/core/res/res/drawable-ldpi/stat_sys_r_signal_2_cdma.png
+++ b/core/res/res/drawable-ldpi/stat_sys_r_signal_2_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_r_signal_3_cdma.png b/core/res/res/drawable-ldpi/stat_sys_r_signal_3_cdma.png
index 9a3f230..47a23c0 100644
--- a/core/res/res/drawable-ldpi/stat_sys_r_signal_3_cdma.png
+++ b/core/res/res/drawable-ldpi/stat_sys_r_signal_3_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_r_signal_4_cdma.png b/core/res/res/drawable-ldpi/stat_sys_r_signal_4_cdma.png
index 5a607ee..b5f259c 100644
--- a/core/res/res/drawable-ldpi/stat_sys_r_signal_4_cdma.png
+++ b/core/res/res/drawable-ldpi/stat_sys_r_signal_4_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_ra_signal_0_cdma.png b/core/res/res/drawable-ldpi/stat_sys_ra_signal_0_cdma.png
index 0db564b..5618e7e 100644
--- a/core/res/res/drawable-ldpi/stat_sys_ra_signal_0_cdma.png
+++ b/core/res/res/drawable-ldpi/stat_sys_ra_signal_0_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_ra_signal_1_cdma.png b/core/res/res/drawable-ldpi/stat_sys_ra_signal_1_cdma.png
index ca697db..5dcde1e 100644
--- a/core/res/res/drawable-ldpi/stat_sys_ra_signal_1_cdma.png
+++ b/core/res/res/drawable-ldpi/stat_sys_ra_signal_1_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_ra_signal_2_cdma.png b/core/res/res/drawable-ldpi/stat_sys_ra_signal_2_cdma.png
index 816aaaa..238ee12 100644
--- a/core/res/res/drawable-ldpi/stat_sys_ra_signal_2_cdma.png
+++ b/core/res/res/drawable-ldpi/stat_sys_ra_signal_2_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_ra_signal_3_cdma.png b/core/res/res/drawable-ldpi/stat_sys_ra_signal_3_cdma.png
index ebb103c..eb72bfa 100644
--- a/core/res/res/drawable-ldpi/stat_sys_ra_signal_3_cdma.png
+++ b/core/res/res/drawable-ldpi/stat_sys_ra_signal_3_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_ra_signal_4_cdma.png b/core/res/res/drawable-ldpi/stat_sys_ra_signal_4_cdma.png
index f211201..91c6657 100644
--- a/core/res/res/drawable-ldpi/stat_sys_ra_signal_4_cdma.png
+++ b/core/res/res/drawable-ldpi/stat_sys_ra_signal_4_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_signal_0_cdma.png b/core/res/res/drawable-ldpi/stat_sys_signal_0_cdma.png
index dabba9c..2e01cfd 100644
--- a/core/res/res/drawable-ldpi/stat_sys_signal_0_cdma.png
+++ b/core/res/res/drawable-ldpi/stat_sys_signal_0_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_signal_1_cdma.png b/core/res/res/drawable-ldpi/stat_sys_signal_1_cdma.png
index 5d99b45..1575832 100644
--- a/core/res/res/drawable-ldpi/stat_sys_signal_1_cdma.png
+++ b/core/res/res/drawable-ldpi/stat_sys_signal_1_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_signal_2_cdma.png b/core/res/res/drawable-ldpi/stat_sys_signal_2_cdma.png
index f68f836..7618aae 100644
--- a/core/res/res/drawable-ldpi/stat_sys_signal_2_cdma.png
+++ b/core/res/res/drawable-ldpi/stat_sys_signal_2_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_signal_3_cdma.png b/core/res/res/drawable-ldpi/stat_sys_signal_3_cdma.png
index 370b91f..2f2d1af 100644
--- a/core/res/res/drawable-ldpi/stat_sys_signal_3_cdma.png
+++ b/core/res/res/drawable-ldpi/stat_sys_signal_3_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_signal_4_cdma.png b/core/res/res/drawable-ldpi/stat_sys_signal_4_cdma.png
index e8b4d38..abe76f2 100644
--- a/core/res/res/drawable-ldpi/stat_sys_signal_4_cdma.png
+++ b/core/res/res/drawable-ldpi/stat_sys_signal_4_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_signal_evdo_0.png b/core/res/res/drawable-ldpi/stat_sys_signal_evdo_0.png
index 2b360c2..3278a9d 100644
--- a/core/res/res/drawable-ldpi/stat_sys_signal_evdo_0.png
+++ b/core/res/res/drawable-ldpi/stat_sys_signal_evdo_0.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_signal_evdo_1.png b/core/res/res/drawable-ldpi/stat_sys_signal_evdo_1.png
index dfcd1f7..39ce722 100644
--- a/core/res/res/drawable-ldpi/stat_sys_signal_evdo_1.png
+++ b/core/res/res/drawable-ldpi/stat_sys_signal_evdo_1.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_signal_evdo_2.png b/core/res/res/drawable-ldpi/stat_sys_signal_evdo_2.png
index b8a5bda..23e6b23 100644
--- a/core/res/res/drawable-ldpi/stat_sys_signal_evdo_2.png
+++ b/core/res/res/drawable-ldpi/stat_sys_signal_evdo_2.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_signal_evdo_3.png b/core/res/res/drawable-ldpi/stat_sys_signal_evdo_3.png
index 65c76d3..c305251 100644
--- a/core/res/res/drawable-ldpi/stat_sys_signal_evdo_3.png
+++ b/core/res/res/drawable-ldpi/stat_sys_signal_evdo_3.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_signal_evdo_4.png b/core/res/res/drawable-ldpi/stat_sys_signal_evdo_4.png
index 974f936..2335528 100644
--- a/core/res/res/drawable-ldpi/stat_sys_signal_evdo_4.png
+++ b/core/res/res/drawable-ldpi/stat_sys_signal_evdo_4.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_throttled.png b/core/res/res/drawable-ldpi/stat_sys_throttled.png
index cfeb3b6..fd117f0 100644
--- a/core/res/res/drawable-ldpi/stat_sys_throttled.png
+++ b/core/res/res/drawable-ldpi/stat_sys_throttled.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_upload_anim0.png b/core/res/res/drawable-ldpi/stat_sys_upload_anim0.png
index 29f9082..98e976f 100644
--- a/core/res/res/drawable-ldpi/stat_sys_upload_anim0.png
+++ b/core/res/res/drawable-ldpi/stat_sys_upload_anim0.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_upload_anim1.png b/core/res/res/drawable-ldpi/stat_sys_upload_anim1.png
index bd1b72a..e881482 100644
--- a/core/res/res/drawable-ldpi/stat_sys_upload_anim1.png
+++ b/core/res/res/drawable-ldpi/stat_sys_upload_anim1.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_upload_anim2.png b/core/res/res/drawable-ldpi/stat_sys_upload_anim2.png
index e49d23b..4a5a3e4 100644
--- a/core/res/res/drawable-ldpi/stat_sys_upload_anim2.png
+++ b/core/res/res/drawable-ldpi/stat_sys_upload_anim2.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_upload_anim3.png b/core/res/res/drawable-ldpi/stat_sys_upload_anim3.png
index 64525ac..ec85a5a 100644
--- a/core/res/res/drawable-ldpi/stat_sys_upload_anim3.png
+++ b/core/res/res/drawable-ldpi/stat_sys_upload_anim3.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_upload_anim4.png b/core/res/res/drawable-ldpi/stat_sys_upload_anim4.png
index 20f8f59..677ef47 100644
--- a/core/res/res/drawable-ldpi/stat_sys_upload_anim4.png
+++ b/core/res/res/drawable-ldpi/stat_sys_upload_anim4.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_upload_anim5.png b/core/res/res/drawable-ldpi/stat_sys_upload_anim5.png
index 0f482df..6a7c65b 100644
--- a/core/res/res/drawable-ldpi/stat_sys_upload_anim5.png
+++ b/core/res/res/drawable-ldpi/stat_sys_upload_anim5.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_vp_phone_call.png b/core/res/res/drawable-ldpi/stat_sys_vp_phone_call.png
index 504d7a5..d6042eb 100644
--- a/core/res/res/drawable-ldpi/stat_sys_vp_phone_call.png
+++ b/core/res/res/drawable-ldpi/stat_sys_vp_phone_call.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_vp_phone_call_on_hold.png b/core/res/res/drawable-ldpi/stat_sys_vp_phone_call_on_hold.png
index edeef2b..e10db66 100644
--- a/core/res/res/drawable-ldpi/stat_sys_vp_phone_call_on_hold.png
+++ b/core/res/res/drawable-ldpi/stat_sys_vp_phone_call_on_hold.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_warning.png b/core/res/res/drawable-ldpi/stat_sys_warning.png
index 289c6a0..68346b0 100644
--- a/core/res/res/drawable-ldpi/stat_sys_warning.png
+++ b/core/res/res/drawable-ldpi/stat_sys_warning.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/status_bar_background.png b/core/res/res/drawable-ldpi/status_bar_background.png
index 7881bce..e103d2e 100644
--- a/core/res/res/drawable-ldpi/status_bar_background.png
+++ b/core/res/res/drawable-ldpi/status_bar_background.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/status_bar_header_background.9.png b/core/res/res/drawable-ldpi/status_bar_header_background.9.png
index 74dddb9..afa6b02 100644
--- a/core/res/res/drawable-ldpi/status_bar_header_background.9.png
+++ b/core/res/res/drawable-ldpi/status_bar_header_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/status_bar_item_app_background_normal.9.png b/core/res/res/drawable-ldpi/status_bar_item_app_background_normal.9.png
index f8cfe2c..2d4851e 100644
--- a/core/res/res/drawable-ldpi/status_bar_item_app_background_normal.9.png
+++ b/core/res/res/drawable-ldpi/status_bar_item_app_background_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/status_bar_item_background_focus.9.png b/core/res/res/drawable-ldpi/status_bar_item_background_focus.9.png
index 07cd873..0da7d52 100644
--- a/core/res/res/drawable-ldpi/status_bar_item_background_focus.9.png
+++ b/core/res/res/drawable-ldpi/status_bar_item_background_focus.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/status_bar_item_background_normal.9.png b/core/res/res/drawable-ldpi/status_bar_item_background_normal.9.png
index e07f774..58e6c51 100644
--- a/core/res/res/drawable-ldpi/status_bar_item_background_normal.9.png
+++ b/core/res/res/drawable-ldpi/status_bar_item_background_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/status_bar_item_background_pressed.9.png b/core/res/res/drawable-ldpi/status_bar_item_background_pressed.9.png
index aea2f5f..eb11610 100644
--- a/core/res/res/drawable-ldpi/status_bar_item_background_pressed.9.png
+++ b/core/res/res/drawable-ldpi/status_bar_item_background_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/submenu_arrow_nofocus.png b/core/res/res/drawable-ldpi/submenu_arrow_nofocus.png
index ce30b58..8c9eff1 100644
--- a/core/res/res/drawable-ldpi/submenu_arrow_nofocus.png
+++ b/core/res/res/drawable-ldpi/submenu_arrow_nofocus.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/sym_action_add.png b/core/res/res/drawable-ldpi/sym_action_add.png
index 7afaede..1a22926 100644
--- a/core/res/res/drawable-ldpi/sym_action_add.png
+++ b/core/res/res/drawable-ldpi/sym_action_add.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/sym_action_call.png b/core/res/res/drawable-ldpi/sym_action_call.png
index 190572d..f05a5fb 100644
--- a/core/res/res/drawable-ldpi/sym_action_call.png
+++ b/core/res/res/drawable-ldpi/sym_action_call.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/sym_action_chat.png b/core/res/res/drawable-ldpi/sym_action_chat.png
index 4eeb59b..4c58eaf 100644
--- a/core/res/res/drawable-ldpi/sym_action_chat.png
+++ b/core/res/res/drawable-ldpi/sym_action_chat.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/sym_action_email.png b/core/res/res/drawable-ldpi/sym_action_email.png
index 47dc63a..55a546d 100644
--- a/core/res/res/drawable-ldpi/sym_action_email.png
+++ b/core/res/res/drawable-ldpi/sym_action_email.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/sym_call_incoming.png b/core/res/res/drawable-ldpi/sym_call_incoming.png
index ec609c6..6eeb463 100644
--- a/core/res/res/drawable-ldpi/sym_call_incoming.png
+++ b/core/res/res/drawable-ldpi/sym_call_incoming.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/sym_call_missed.png b/core/res/res/drawable-ldpi/sym_call_missed.png
index 8bad634..0898b67 100644
--- a/core/res/res/drawable-ldpi/sym_call_missed.png
+++ b/core/res/res/drawable-ldpi/sym_call_missed.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/sym_call_outgoing.png b/core/res/res/drawable-ldpi/sym_call_outgoing.png
index 362df01..b4c8a25 100644
--- a/core/res/res/drawable-ldpi/sym_call_outgoing.png
+++ b/core/res/res/drawable-ldpi/sym_call_outgoing.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/sym_contact_card.png b/core/res/res/drawable-ldpi/sym_contact_card.png
index 8ffd06e..4d0089e4 100644
--- a/core/res/res/drawable-ldpi/sym_contact_card.png
+++ b/core/res/res/drawable-ldpi/sym_contact_card.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/sym_keyboard_delete.png b/core/res/res/drawable-ldpi/sym_keyboard_delete.png
index d9d5653..87aec1d 100644
--- a/core/res/res/drawable-ldpi/sym_keyboard_delete.png
+++ b/core/res/res/drawable-ldpi/sym_keyboard_delete.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/sym_keyboard_delete_dim.png b/core/res/res/drawable-ldpi/sym_keyboard_delete_dim.png
index d7d9385..615f777 100644
--- a/core/res/res/drawable-ldpi/sym_keyboard_delete_dim.png
+++ b/core/res/res/drawable-ldpi/sym_keyboard_delete_dim.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/sym_keyboard_feedback_delete.png b/core/res/res/drawable-ldpi/sym_keyboard_feedback_delete.png
index 8922bf9..2d689c9 100644
--- a/core/res/res/drawable-ldpi/sym_keyboard_feedback_delete.png
+++ b/core/res/res/drawable-ldpi/sym_keyboard_feedback_delete.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/sym_keyboard_feedback_ok.png b/core/res/res/drawable-ldpi/sym_keyboard_feedback_ok.png
index 304141b5..252cc9c 100644
--- a/core/res/res/drawable-ldpi/sym_keyboard_feedback_ok.png
+++ b/core/res/res/drawable-ldpi/sym_keyboard_feedback_ok.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/sym_keyboard_feedback_return.png b/core/res/res/drawable-ldpi/sym_keyboard_feedback_return.png
index c5f3247..7e8c66b 100644
--- a/core/res/res/drawable-ldpi/sym_keyboard_feedback_return.png
+++ b/core/res/res/drawable-ldpi/sym_keyboard_feedback_return.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/sym_keyboard_feedback_shift.png b/core/res/res/drawable-ldpi/sym_keyboard_feedback_shift.png
index a7bf565..7692508 100644
--- a/core/res/res/drawable-ldpi/sym_keyboard_feedback_shift.png
+++ b/core/res/res/drawable-ldpi/sym_keyboard_feedback_shift.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/sym_keyboard_feedback_shift_locked.png b/core/res/res/drawable-ldpi/sym_keyboard_feedback_shift_locked.png
index 114abac..1cebda6e 100644
--- a/core/res/res/drawable-ldpi/sym_keyboard_feedback_shift_locked.png
+++ b/core/res/res/drawable-ldpi/sym_keyboard_feedback_shift_locked.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/sym_keyboard_feedback_space.png b/core/res/res/drawable-ldpi/sym_keyboard_feedback_space.png
index 5d52970..83f37db 100644
--- a/core/res/res/drawable-ldpi/sym_keyboard_feedback_space.png
+++ b/core/res/res/drawable-ldpi/sym_keyboard_feedback_space.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/sym_keyboard_num0_no_plus.png b/core/res/res/drawable-ldpi/sym_keyboard_num0_no_plus.png
index eb4764d..96d38d8 100644
--- a/core/res/res/drawable-ldpi/sym_keyboard_num0_no_plus.png
+++ b/core/res/res/drawable-ldpi/sym_keyboard_num0_no_plus.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/sym_keyboard_num1.png b/core/res/res/drawable-ldpi/sym_keyboard_num1.png
index 1339b6d..1f6bf71 100644
--- a/core/res/res/drawable-ldpi/sym_keyboard_num1.png
+++ b/core/res/res/drawable-ldpi/sym_keyboard_num1.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/sym_keyboard_num2.png b/core/res/res/drawable-ldpi/sym_keyboard_num2.png
index bd2379d..6c4d0ee 100644
--- a/core/res/res/drawable-ldpi/sym_keyboard_num2.png
+++ b/core/res/res/drawable-ldpi/sym_keyboard_num2.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/sym_keyboard_num3.png b/core/res/res/drawable-ldpi/sym_keyboard_num3.png
index 43e8b15..760a23d 100644
--- a/core/res/res/drawable-ldpi/sym_keyboard_num3.png
+++ b/core/res/res/drawable-ldpi/sym_keyboard_num3.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/sym_keyboard_num4.png b/core/res/res/drawable-ldpi/sym_keyboard_num4.png
index 70d4f78..6116aa7 100644
--- a/core/res/res/drawable-ldpi/sym_keyboard_num4.png
+++ b/core/res/res/drawable-ldpi/sym_keyboard_num4.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/sym_keyboard_num5.png b/core/res/res/drawable-ldpi/sym_keyboard_num5.png
index 5acda28..597c741 100644
--- a/core/res/res/drawable-ldpi/sym_keyboard_num5.png
+++ b/core/res/res/drawable-ldpi/sym_keyboard_num5.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/sym_keyboard_num6.png b/core/res/res/drawable-ldpi/sym_keyboard_num6.png
index 950600b0..b2d795d 100644
--- a/core/res/res/drawable-ldpi/sym_keyboard_num6.png
+++ b/core/res/res/drawable-ldpi/sym_keyboard_num6.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/sym_keyboard_num7.png b/core/res/res/drawable-ldpi/sym_keyboard_num7.png
index caea4bb..7928f5b 100644
--- a/core/res/res/drawable-ldpi/sym_keyboard_num7.png
+++ b/core/res/res/drawable-ldpi/sym_keyboard_num7.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/sym_keyboard_num8.png b/core/res/res/drawable-ldpi/sym_keyboard_num8.png
index b528fc7..2aef281 100644
--- a/core/res/res/drawable-ldpi/sym_keyboard_num8.png
+++ b/core/res/res/drawable-ldpi/sym_keyboard_num8.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/sym_keyboard_num9.png b/core/res/res/drawable-ldpi/sym_keyboard_num9.png
index 1835e21..38e77cdc 100644
--- a/core/res/res/drawable-ldpi/sym_keyboard_num9.png
+++ b/core/res/res/drawable-ldpi/sym_keyboard_num9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/sym_keyboard_ok.png b/core/res/res/drawable-ldpi/sym_keyboard_ok.png
index 70bffc1..7fb9202f 100644
--- a/core/res/res/drawable-ldpi/sym_keyboard_ok.png
+++ b/core/res/res/drawable-ldpi/sym_keyboard_ok.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/sym_keyboard_ok_dim.png b/core/res/res/drawable-ldpi/sym_keyboard_ok_dim.png
index 01cf616..ae68542 100644
--- a/core/res/res/drawable-ldpi/sym_keyboard_ok_dim.png
+++ b/core/res/res/drawable-ldpi/sym_keyboard_ok_dim.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/sym_keyboard_return.png b/core/res/res/drawable-ldpi/sym_keyboard_return.png
index 1c7c58d..ca402b2 100644
--- a/core/res/res/drawable-ldpi/sym_keyboard_return.png
+++ b/core/res/res/drawable-ldpi/sym_keyboard_return.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/sym_keyboard_shift.png b/core/res/res/drawable-ldpi/sym_keyboard_shift.png
index 382a08f..921acbe 100644
--- a/core/res/res/drawable-ldpi/sym_keyboard_shift.png
+++ b/core/res/res/drawable-ldpi/sym_keyboard_shift.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/sym_keyboard_shift_locked.png b/core/res/res/drawable-ldpi/sym_keyboard_shift_locked.png
index c644eff..8a75ef6 100644
--- a/core/res/res/drawable-ldpi/sym_keyboard_shift_locked.png
+++ b/core/res/res/drawable-ldpi/sym_keyboard_shift_locked.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/sym_keyboard_space.png b/core/res/res/drawable-ldpi/sym_keyboard_space.png
index 0b91646..101348a 100644
--- a/core/res/res/drawable-ldpi/sym_keyboard_space.png
+++ b/core/res/res/drawable-ldpi/sym_keyboard_space.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/tab_focus.9.png b/core/res/res/drawable-ldpi/tab_focus.9.png
index 59a0b65..5d59262 100644
--- a/core/res/res/drawable-ldpi/tab_focus.9.png
+++ b/core/res/res/drawable-ldpi/tab_focus.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/tab_focus_bar_left.9.png b/core/res/res/drawable-ldpi/tab_focus_bar_left.9.png
index 0ee8347..4463273 100644
--- a/core/res/res/drawable-ldpi/tab_focus_bar_left.9.png
+++ b/core/res/res/drawable-ldpi/tab_focus_bar_left.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/tab_focus_bar_right.9.png b/core/res/res/drawable-ldpi/tab_focus_bar_right.9.png
index 0ee8347..992612b 100644
--- a/core/res/res/drawable-ldpi/tab_focus_bar_right.9.png
+++ b/core/res/res/drawable-ldpi/tab_focus_bar_right.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/tab_press.9.png b/core/res/res/drawable-ldpi/tab_press.9.png
index ba9c82d..6dd872d 100644
--- a/core/res/res/drawable-ldpi/tab_press.9.png
+++ b/core/res/res/drawable-ldpi/tab_press.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/tab_press_bar_left.9.png b/core/res/res/drawable-ldpi/tab_press_bar_left.9.png
index ee129ba..89de9d5 100644
--- a/core/res/res/drawable-ldpi/tab_press_bar_left.9.png
+++ b/core/res/res/drawable-ldpi/tab_press_bar_left.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/tab_press_bar_right.9.png b/core/res/res/drawable-ldpi/tab_press_bar_right.9.png
index ee129ba..fb38479 100644
--- a/core/res/res/drawable-ldpi/tab_press_bar_right.9.png
+++ b/core/res/res/drawable-ldpi/tab_press_bar_right.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/tab_selected.9.png b/core/res/res/drawable-ldpi/tab_selected.9.png
index 318f09f..6fdd76a 100644
--- a/core/res/res/drawable-ldpi/tab_selected.9.png
+++ b/core/res/res/drawable-ldpi/tab_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/tab_selected_bar_left.9.png b/core/res/res/drawable-ldpi/tab_selected_bar_left.9.png
index 03bcc13..06aad39 100644
--- a/core/res/res/drawable-ldpi/tab_selected_bar_left.9.png
+++ b/core/res/res/drawable-ldpi/tab_selected_bar_left.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/tab_selected_bar_left_v4.9.png b/core/res/res/drawable-ldpi/tab_selected_bar_left_v4.9.png
index e7a07255..92cd997 100644
--- a/core/res/res/drawable-ldpi/tab_selected_bar_left_v4.9.png
+++ b/core/res/res/drawable-ldpi/tab_selected_bar_left_v4.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/tab_selected_bar_right.9.png b/core/res/res/drawable-ldpi/tab_selected_bar_right.9.png
index f228445..06aad39 100644
--- a/core/res/res/drawable-ldpi/tab_selected_bar_right.9.png
+++ b/core/res/res/drawable-ldpi/tab_selected_bar_right.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/tab_selected_bar_right_v4.9.png b/core/res/res/drawable-ldpi/tab_selected_bar_right_v4.9.png
index e7a07255..92cd997 100644
--- a/core/res/res/drawable-ldpi/tab_selected_bar_right_v4.9.png
+++ b/core/res/res/drawable-ldpi/tab_selected_bar_right_v4.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/tab_selected_v4.9.png b/core/res/res/drawable-ldpi/tab_selected_v4.9.png
index 2ad1757..247f4bf 100644
--- a/core/res/res/drawable-ldpi/tab_selected_v4.9.png
+++ b/core/res/res/drawable-ldpi/tab_selected_v4.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/tab_unselected.9.png b/core/res/res/drawable-ldpi/tab_unselected.9.png
index de7c467..a36e5a1 100644
--- a/core/res/res/drawable-ldpi/tab_unselected.9.png
+++ b/core/res/res/drawable-ldpi/tab_unselected.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/tab_unselected_v4.9.png b/core/res/res/drawable-ldpi/tab_unselected_v4.9.png
index 61d4ef0..8855539 100644
--- a/core/res/res/drawable-ldpi/tab_unselected_v4.9.png
+++ b/core/res/res/drawable-ldpi/tab_unselected_v4.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/textfield_default.9.png b/core/res/res/drawable-ldpi/textfield_default.9.png
index 4cfa745..8a27dac 100644
--- a/core/res/res/drawable-ldpi/textfield_default.9.png
+++ b/core/res/res/drawable-ldpi/textfield_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/textfield_disabled.9.png b/core/res/res/drawable-ldpi/textfield_disabled.9.png
index e54bf30..fcc1e3b 100644
--- a/core/res/res/drawable-ldpi/textfield_disabled.9.png
+++ b/core/res/res/drawable-ldpi/textfield_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/textfield_disabled_selected.9.png b/core/res/res/drawable-ldpi/textfield_disabled_selected.9.png
index 02f6b5e..41f43ee 100644
--- a/core/res/res/drawable-ldpi/textfield_disabled_selected.9.png
+++ b/core/res/res/drawable-ldpi/textfield_disabled_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/textfield_search_default.9.png b/core/res/res/drawable-ldpi/textfield_search_default.9.png
index dfb3f7a..3642b3e 100644
--- a/core/res/res/drawable-ldpi/textfield_search_default.9.png
+++ b/core/res/res/drawable-ldpi/textfield_search_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/textfield_search_empty_default.9.png b/core/res/res/drawable-ldpi/textfield_search_empty_default.9.png
index 65fbe33..7c30dad 100644
--- a/core/res/res/drawable-ldpi/textfield_search_empty_default.9.png
+++ b/core/res/res/drawable-ldpi/textfield_search_empty_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/textfield_search_empty_pressed.9.png b/core/res/res/drawable-ldpi/textfield_search_empty_pressed.9.png
index 2a72142..2b3e4e4 100644
--- a/core/res/res/drawable-ldpi/textfield_search_empty_pressed.9.png
+++ b/core/res/res/drawable-ldpi/textfield_search_empty_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/textfield_search_empty_selected.9.png b/core/res/res/drawable-ldpi/textfield_search_empty_selected.9.png
index 162c178..643c4d3 100644
--- a/core/res/res/drawable-ldpi/textfield_search_empty_selected.9.png
+++ b/core/res/res/drawable-ldpi/textfield_search_empty_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/textfield_search_pressed.9.png b/core/res/res/drawable-ldpi/textfield_search_pressed.9.png
index b414f6c..bcf99ce 100644
--- a/core/res/res/drawable-ldpi/textfield_search_pressed.9.png
+++ b/core/res/res/drawable-ldpi/textfield_search_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/textfield_search_selected.9.png b/core/res/res/drawable-ldpi/textfield_search_selected.9.png
index d6e6a44..17bb62e 100644
--- a/core/res/res/drawable-ldpi/textfield_search_selected.9.png
+++ b/core/res/res/drawable-ldpi/textfield_search_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/textfield_selected.9.png b/core/res/res/drawable-ldpi/textfield_selected.9.png
index 80a6f39..0f0252a 100644
--- a/core/res/res/drawable-ldpi/textfield_selected.9.png
+++ b/core/res/res/drawable-ldpi/textfield_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/title_bar_medium.9.png b/core/res/res/drawable-ldpi/title_bar_medium.9.png
index ab95aad..4ef6113 100644
--- a/core/res/res/drawable-ldpi/title_bar_medium.9.png
+++ b/core/res/res/drawable-ldpi/title_bar_medium.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/title_bar_portrait.9.png b/core/res/res/drawable-ldpi/title_bar_portrait.9.png
index 6f868db..3a2a7ac 100644
--- a/core/res/res/drawable-ldpi/title_bar_portrait.9.png
+++ b/core/res/res/drawable-ldpi/title_bar_portrait.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/title_bar_tall.9.png b/core/res/res/drawable-ldpi/title_bar_tall.9.png
index b4729b7..043fb3b 100644
--- a/core/res/res/drawable-ldpi/title_bar_tall.9.png
+++ b/core/res/res/drawable-ldpi/title_bar_tall.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/unknown_image.png b/core/res/res/drawable-ldpi/unknown_image.png
index c6255ba..4b56ce7 100644
--- a/core/res/res/drawable-ldpi/unknown_image.png
+++ b/core/res/res/drawable-ldpi/unknown_image.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/vpn_connected.png b/core/res/res/drawable-ldpi/vpn_connected.png
index 65fc6db..7b42a13 100644
--- a/core/res/res/drawable-ldpi/vpn_connected.png
+++ b/core/res/res/drawable-ldpi/vpn_connected.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/vpn_disconnected.png b/core/res/res/drawable-ldpi/vpn_disconnected.png
index 2440c69..ceb0bd2 100644
--- a/core/res/res/drawable-ldpi/vpn_disconnected.png
+++ b/core/res/res/drawable-ldpi/vpn_disconnected.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/zoom_plate.9.png b/core/res/res/drawable-ldpi/zoom_plate.9.png
index 5e34e7a..dd69fde 100644
--- a/core/res/res/drawable-ldpi/zoom_plate.9.png
+++ b/core/res/res/drawable-ldpi/zoom_plate.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_bottom_solid_dark_holo.9.png b/core/res/res/drawable-mdpi/ab_bottom_solid_dark_holo.9.png
index b229367..06d96feea 100644
--- a/core/res/res/drawable-mdpi/ab_bottom_solid_dark_holo.9.png
+++ b/core/res/res/drawable-mdpi/ab_bottom_solid_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_bottom_solid_inverse_holo.9.png b/core/res/res/drawable-mdpi/ab_bottom_solid_inverse_holo.9.png
index c65f443..287bd76 100644
--- a/core/res/res/drawable-mdpi/ab_bottom_solid_inverse_holo.9.png
+++ b/core/res/res/drawable-mdpi/ab_bottom_solid_inverse_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_bottom_solid_light_holo.9.png b/core/res/res/drawable-mdpi/ab_bottom_solid_light_holo.9.png
index 0706c8a..781d387 100644
--- a/core/res/res/drawable-mdpi/ab_bottom_solid_light_holo.9.png
+++ b/core/res/res/drawable-mdpi/ab_bottom_solid_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_bottom_transparent_dark_holo.9.png b/core/res/res/drawable-mdpi/ab_bottom_transparent_dark_holo.9.png
index d814d02..c7be4aa 100644
--- a/core/res/res/drawable-mdpi/ab_bottom_transparent_dark_holo.9.png
+++ b/core/res/res/drawable-mdpi/ab_bottom_transparent_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_bottom_transparent_light_holo.9.png b/core/res/res/drawable-mdpi/ab_bottom_transparent_light_holo.9.png
index b139c8e..3faf7cc 100644
--- a/core/res/res/drawable-mdpi/ab_bottom_transparent_light_holo.9.png
+++ b/core/res/res/drawable-mdpi/ab_bottom_transparent_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_share_pack_holo_dark.9.png b/core/res/res/drawable-mdpi/ab_share_pack_holo_dark.9.png
index ed4ba34..ab71221 100644
--- a/core/res/res/drawable-mdpi/ab_share_pack_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/ab_share_pack_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_share_pack_holo_light.9.png b/core/res/res/drawable-mdpi/ab_share_pack_holo_light.9.png
index 8f10bd5..3b05e83 100644
--- a/core/res/res/drawable-mdpi/ab_share_pack_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/ab_share_pack_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_share_pack_mtrl_alpha.9.png b/core/res/res/drawable-mdpi/ab_share_pack_mtrl_alpha.9.png
index f31730d..3b1ff08 100644
--- a/core/res/res/drawable-mdpi/ab_share_pack_mtrl_alpha.9.png
+++ b/core/res/res/drawable-mdpi/ab_share_pack_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_solid_dark_holo.9.png b/core/res/res/drawable-mdpi/ab_solid_dark_holo.9.png
index 743d00b..75d738c 100644
--- a/core/res/res/drawable-mdpi/ab_solid_dark_holo.9.png
+++ b/core/res/res/drawable-mdpi/ab_solid_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_solid_light_holo.9.png b/core/res/res/drawable-mdpi/ab_solid_light_holo.9.png
index 17c1fb9..8ea3380 100644
--- a/core/res/res/drawable-mdpi/ab_solid_light_holo.9.png
+++ b/core/res/res/drawable-mdpi/ab_solid_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_solid_shadow_holo.9.png b/core/res/res/drawable-mdpi/ab_solid_shadow_holo.9.png
index ddfc8e3..ab53f48 100644
--- a/core/res/res/drawable-mdpi/ab_solid_shadow_holo.9.png
+++ b/core/res/res/drawable-mdpi/ab_solid_shadow_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_solid_shadow_mtrl_alpha.9.png b/core/res/res/drawable-mdpi/ab_solid_shadow_mtrl_alpha.9.png
index ebdea00..2ad3026 100644
--- a/core/res/res/drawable-mdpi/ab_solid_shadow_mtrl_alpha.9.png
+++ b/core/res/res/drawable-mdpi/ab_solid_shadow_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_stacked_solid_dark_holo.9.png b/core/res/res/drawable-mdpi/ab_stacked_solid_dark_holo.9.png
index 007a4b2..f6b4784 100644
--- a/core/res/res/drawable-mdpi/ab_stacked_solid_dark_holo.9.png
+++ b/core/res/res/drawable-mdpi/ab_stacked_solid_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_stacked_solid_inverse_holo.9.png b/core/res/res/drawable-mdpi/ab_stacked_solid_inverse_holo.9.png
index a823841..b4c96d7 100644
--- a/core/res/res/drawable-mdpi/ab_stacked_solid_inverse_holo.9.png
+++ b/core/res/res/drawable-mdpi/ab_stacked_solid_inverse_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_stacked_solid_light_holo.9.png b/core/res/res/drawable-mdpi/ab_stacked_solid_light_holo.9.png
index ad6e1a4..dc77fee 100644
--- a/core/res/res/drawable-mdpi/ab_stacked_solid_light_holo.9.png
+++ b/core/res/res/drawable-mdpi/ab_stacked_solid_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_stacked_transparent_dark_holo.9.png b/core/res/res/drawable-mdpi/ab_stacked_transparent_dark_holo.9.png
index 0ad6c88..fc43584 100644
--- a/core/res/res/drawable-mdpi/ab_stacked_transparent_dark_holo.9.png
+++ b/core/res/res/drawable-mdpi/ab_stacked_transparent_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_stacked_transparent_light_holo.9.png b/core/res/res/drawable-mdpi/ab_stacked_transparent_light_holo.9.png
index 19b50ab..fd797a0 100644
--- a/core/res/res/drawable-mdpi/ab_stacked_transparent_light_holo.9.png
+++ b/core/res/res/drawable-mdpi/ab_stacked_transparent_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_transparent_dark_holo.9.png b/core/res/res/drawable-mdpi/ab_transparent_dark_holo.9.png
index ad980b1..7a550fc 100644
--- a/core/res/res/drawable-mdpi/ab_transparent_dark_holo.9.png
+++ b/core/res/res/drawable-mdpi/ab_transparent_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_transparent_light_holo.9.png b/core/res/res/drawable-mdpi/ab_transparent_light_holo.9.png
index 60e6c52..400ddaa 100644
--- a/core/res/res/drawable-mdpi/ab_transparent_light_holo.9.png
+++ b/core/res/res/drawable-mdpi/ab_transparent_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/activity_title_bar.9.png b/core/res/res/drawable-mdpi/activity_title_bar.9.png
index bd0680d..c3d29a0 100644
--- a/core/res/res/drawable-mdpi/activity_title_bar.9.png
+++ b/core/res/res/drawable-mdpi/activity_title_bar.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/arrow_down_float.png b/core/res/res/drawable-mdpi/arrow_down_float.png
index dd82523..2ca994e 100644
--- a/core/res/res/drawable-mdpi/arrow_down_float.png
+++ b/core/res/res/drawable-mdpi/arrow_down_float.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/arrow_up_float.png b/core/res/res/drawable-mdpi/arrow_up_float.png
index 9bc3d1c..4da8ea3 100644
--- a/core/res/res/drawable-mdpi/arrow_up_float.png
+++ b/core/res/res/drawable-mdpi/arrow_up_float.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/battery_charge_background.png b/core/res/res/drawable-mdpi/battery_charge_background.png
index 9219745..971db27 100644
--- a/core/res/res/drawable-mdpi/battery_charge_background.png
+++ b/core/res/res/drawable-mdpi/battery_charge_background.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/bottom_bar.png b/core/res/res/drawable-mdpi/bottom_bar.png
index 1fdb078..9618c55 100644
--- a/core/res/res/drawable-mdpi/bottom_bar.png
+++ b/core/res/res/drawable-mdpi/bottom_bar.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_cab_done_default_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_cab_done_default_holo_dark.9.png
index 5461b9c..1ecbccb 100644
--- a/core/res/res/drawable-mdpi/btn_cab_done_default_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_cab_done_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_cab_done_default_holo_light.9.png b/core/res/res/drawable-mdpi/btn_cab_done_default_holo_light.9.png
index 5dc6f80..96fe8ea 100644
--- a/core/res/res/drawable-mdpi/btn_cab_done_default_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_cab_done_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_cab_done_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_cab_done_focused_holo_dark.9.png
index a70b53c..52fae79 100644
--- a/core/res/res/drawable-mdpi/btn_cab_done_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_cab_done_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_cab_done_focused_holo_light.9.png b/core/res/res/drawable-mdpi/btn_cab_done_focused_holo_light.9.png
index c7a9896..1e814a8 100644
--- a/core/res/res/drawable-mdpi/btn_cab_done_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_cab_done_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_cab_done_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_cab_done_pressed_holo_dark.9.png
index f4185d1..bc7532b 100644
--- a/core/res/res/drawable-mdpi/btn_cab_done_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_cab_done_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_cab_done_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/btn_cab_done_pressed_holo_light.9.png
index d59219b..bd97ca0 100644
--- a/core/res/res/drawable-mdpi/btn_cab_done_pressed_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_cab_done_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_buttonless_off.png b/core/res/res/drawable-mdpi/btn_check_buttonless_off.png
index f8972fc..2e4ab89 100644
--- a/core/res/res/drawable-mdpi/btn_check_buttonless_off.png
+++ b/core/res/res/drawable-mdpi/btn_check_buttonless_off.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_buttonless_on.png b/core/res/res/drawable-mdpi/btn_check_buttonless_on.png
index a10a37a..605565d 100644
--- a/core/res/res/drawable-mdpi/btn_check_buttonless_on.png
+++ b/core/res/res/drawable-mdpi/btn_check_buttonless_on.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_label_background.9.png b/core/res/res/drawable-mdpi/btn_check_label_background.9.png
index 79367b8..88e84be 100644
--- a/core/res/res/drawable-mdpi/btn_check_label_background.9.png
+++ b/core/res/res/drawable-mdpi/btn_check_label_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off.png b/core/res/res/drawable-mdpi/btn_check_off.png
index b0541d9..f78e788 100644
--- a/core/res/res/drawable-mdpi/btn_check_off.png
+++ b/core/res/res/drawable-mdpi/btn_check_off.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_disable.png b/core/res/res/drawable-mdpi/btn_check_off_disable.png
index 5ec8d03..643f2c8 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_disable.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_disable.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_disable_focused.png b/core/res/res/drawable-mdpi/btn_check_off_disable_focused.png
index 341ffb9..b86628f 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_disable_focused.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_disable_focused_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_off_disable_focused_holo_dark.png
index f3194b7..30e47e3 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_disable_focused_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_disable_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_disable_focused_holo_light.png b/core/res/res/drawable-mdpi/btn_check_off_disable_focused_holo_light.png
index bd71072..439908c 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_disable_focused_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_disable_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_disable_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_off_disable_holo_dark.png
index f3194b7..30e47e3 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_disable_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_disable_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_disable_holo_light.png b/core/res/res/drawable-mdpi/btn_check_off_disable_holo_light.png
index bd71072..439908c 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_disable_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_disable_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_disabled_focused_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_off_disabled_focused_holo_dark.png
index 049cd28..305e6e2 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_disabled_focused_holo_light.png b/core/res/res/drawable-mdpi/btn_check_off_disabled_focused_holo_light.png
index 42442e8..1666466 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_disabled_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_off_disabled_holo_dark.png
index 654d449..f765280 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_disabled_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_disabled_holo_light.png b/core/res/res/drawable-mdpi/btn_check_off_disabled_holo_light.png
index db19043..1ef36a8 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_disabled_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_focused_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_off_focused_holo_dark.png
index a09cd48..d835aaa 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_focused_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_focused_holo_light.png b/core/res/res/drawable-mdpi/btn_check_off_focused_holo_light.png
index 3fc71fd..50d0c9d 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_focused_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_holo.png b/core/res/res/drawable-mdpi/btn_check_off_holo.png
index 8655e0c..b8ea33a 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_holo.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_off_holo_dark.png
index 6081079..4cf6b23 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_holo_light.png b/core/res/res/drawable-mdpi/btn_check_off_holo_light.png
index 5e04a57..bbea961 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_normal_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_off_normal_holo_dark.png
index 1561176..7c1c9a2 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_normal_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_normal_holo_light.png b/core/res/res/drawable-mdpi/btn_check_off_normal_holo_light.png
index b39ad3d..e39abd7 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_normal_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_pressed.png b/core/res/res/drawable-mdpi/btn_check_off_pressed.png
index 5e77a77..a5fe0d5 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_pressed.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_pressed_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_off_pressed_holo_dark.png
index 47e8b5b..44f7985 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_pressed_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_pressed_holo_light.png b/core/res/res/drawable-mdpi/btn_check_off_pressed_holo_light.png
index 1dc83fa..fee7819 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_pressed_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_selected.png b/core/res/res/drawable-mdpi/btn_check_off_selected.png
index 4e40f207..f01d3d9 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_selected.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_selected.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on.png b/core/res/res/drawable-mdpi/btn_check_on.png
index 23304a1..2b24205 100644
--- a/core/res/res/drawable-mdpi/btn_check_on.png
+++ b/core/res/res/drawable-mdpi/btn_check_on.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_disable.png b/core/res/res/drawable-mdpi/btn_check_on_disable.png
index 817745c..9dfbfb9 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_disable.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_disable.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_disable_focused.png b/core/res/res/drawable-mdpi/btn_check_on_disable_focused.png
index 13d13b6..7b378b6 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_disable_focused.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_disable_focused_holo_light.png b/core/res/res/drawable-mdpi/btn_check_on_disable_focused_holo_light.png
index c9ebbca..d47b492 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_disable_focused_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_disable_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_disable_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_on_disable_holo_dark.png
index 48cc017..d307a5f 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_disable_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_disable_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_disable_holo_light.png b/core/res/res/drawable-mdpi/btn_check_on_disable_holo_light.png
index c9ebbca..d47b492 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_disable_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_disable_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_disabled_focused_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_on_disabled_focused_holo_dark.png
index 29fa22f..e70d950 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_disabled_focused_holo_light.png b/core/res/res/drawable-mdpi/btn_check_on_disabled_focused_holo_light.png
index 997045d..d7cdb64 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_disabled_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_on_disabled_holo_dark.png
index e180ea7..3965044 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_disabled_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_disabled_holo_light.png b/core/res/res/drawable-mdpi/btn_check_on_disabled_holo_light.png
index 20e2aab..b2e716e 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_disabled_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_focused_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_on_focused_holo_dark.png
index 9c089aa..f0df607 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_focused_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_focused_holo_light.png b/core/res/res/drawable-mdpi/btn_check_on_focused_holo_light.png
index a3b4916..504f6fa 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_focused_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_holo.png b/core/res/res/drawable-mdpi/btn_check_on_holo.png
index 2737d8c..0061c64 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_holo.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_on_holo_dark.png
index 9f31c1b..1a868f2 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_holo_light.png b/core/res/res/drawable-mdpi/btn_check_on_holo_light.png
index f657c5b..e8b6a98 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_pressed.png b/core/res/res/drawable-mdpi/btn_check_on_pressed.png
index 9cdc796..be6d0f8 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_pressed.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_dark.png
index eafc553..02d3641 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_light.png b/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_light.png
index 6583e99..d469e0d 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_selected.png b/core/res/res/drawable-mdpi/btn_check_on_selected.png
index b2c3727..9c8218d 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_selected.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_selected.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_circle_disable.png b/core/res/res/drawable-mdpi/btn_circle_disable.png
index 29e227c..1fa267e 100644
--- a/core/res/res/drawable-mdpi/btn_circle_disable.png
+++ b/core/res/res/drawable-mdpi/btn_circle_disable.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_circle_disable_focused.png b/core/res/res/drawable-mdpi/btn_circle_disable_focused.png
index c5aa3c5..b28aea2 100644
--- a/core/res/res/drawable-mdpi/btn_circle_disable_focused.png
+++ b/core/res/res/drawable-mdpi/btn_circle_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_circle_normal.png b/core/res/res/drawable-mdpi/btn_circle_normal.png
index 6358351..a01c0c7 100644
--- a/core/res/res/drawable-mdpi/btn_circle_normal.png
+++ b/core/res/res/drawable-mdpi/btn_circle_normal.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_circle_pressed.png b/core/res/res/drawable-mdpi/btn_circle_pressed.png
index dc07a61..71ca541 100644
--- a/core/res/res/drawable-mdpi/btn_circle_pressed.png
+++ b/core/res/res/drawable-mdpi/btn_circle_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_circle_selected.png b/core/res/res/drawable-mdpi/btn_circle_selected.png
index 6eb2ff5..2aa315a 100644
--- a/core/res/res/drawable-mdpi/btn_circle_selected.png
+++ b/core/res/res/drawable-mdpi/btn_circle_selected.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_close_normal.png b/core/res/res/drawable-mdpi/btn_close_normal.png
index eca5828..2f35ea0 100644
--- a/core/res/res/drawable-mdpi/btn_close_normal.png
+++ b/core/res/res/drawable-mdpi/btn_close_normal.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_close_pressed.png b/core/res/res/drawable-mdpi/btn_close_pressed.png
index 3c745bb..6d4294a 100644
--- a/core/res/res/drawable-mdpi/btn_close_pressed.png
+++ b/core/res/res/drawable-mdpi/btn_close_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_close_selected.png b/core/res/res/drawable-mdpi/btn_close_selected.png
index c41f039..d5cd6d4b 100644
--- a/core/res/res/drawable-mdpi/btn_close_selected.png
+++ b/core/res/res/drawable-mdpi/btn_close_selected.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_dark.9.png
index 3ce61b3..a327b6a 100644
--- a/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_light.9.png
index 3ce61b3..a327b6a 100644
--- a/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_holo.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_holo.9.png
index 77f6492..d1e6b91 100644
--- a/core/res/res/drawable-mdpi/btn_default_disabled_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_holo_dark.9.png
index 82e54fd..3ee13a3 100644
--- a/core/res/res/drawable-mdpi/btn_default_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_holo_light.9.png
index 82e54fd..3ee13a3 100644
--- a/core/res/res/drawable-mdpi/btn_default_disabled_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_focused_holo.9.png b/core/res/res/drawable-mdpi/btn_default_focused_holo.9.png
index 683f128..b325a91 100644
--- a/core/res/res/drawable-mdpi/btn_default_focused_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_focused_holo_dark.9.png
index c389871..8f5c7026 100644
--- a/core/res/res/drawable-mdpi/btn_default_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_focused_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_focused_holo_light.9.png
index c389871..8f5c7026 100644
--- a/core/res/res/drawable-mdpi/btn_default_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal.9.png b/core/res/res/drawable-mdpi/btn_default_normal.9.png
index 7ff74b2..c9f0bd2 100644
--- a/core/res/res/drawable-mdpi/btn_default_normal.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal_disable.9.png b/core/res/res/drawable-mdpi/btn_default_normal_disable.9.png
index d3e11b5..fdca1a4 100644
--- a/core/res/res/drawable-mdpi/btn_default_normal_disable.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_normal_disable.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal_disable_focused.9.png b/core/res/res/drawable-mdpi/btn_default_normal_disable_focused.9.png
index 843ca7a..b923d25 100644
--- a/core/res/res/drawable-mdpi/btn_default_normal_disable_focused.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_normal_disable_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal_holo.9.png b/core/res/res/drawable-mdpi/btn_default_normal_holo.9.png
index 0e0da34..a397ca3 100644
--- a/core/res/res/drawable-mdpi/btn_default_normal_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_normal_holo_dark.9.png
index 211be67..be961dd 100644
--- a/core/res/res/drawable-mdpi/btn_default_normal_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_normal_holo_light.9.png
index accc761..2e3ff52 100644
--- a/core/res/res/drawable-mdpi/btn_default_normal_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_pressed.9.png b/core/res/res/drawable-mdpi/btn_default_pressed.9.png
index 74fd58b..e1f90f0 100644
--- a/core/res/res/drawable-mdpi/btn_default_pressed.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_pressed_holo.9.png b/core/res/res/drawable-mdpi/btn_default_pressed_holo.9.png
index 1940216..60d8d15 100644
--- a/core/res/res/drawable-mdpi/btn_default_pressed_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_pressed_holo_dark.9.png
index ebdc717..32919f0 100644
--- a/core/res/res/drawable-mdpi/btn_default_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_pressed_holo_light.9.png
index c73984e..c056367 100644
--- a/core/res/res/drawable-mdpi/btn_default_pressed_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_selected.9.png b/core/res/res/drawable-mdpi/btn_default_selected.9.png
index 415b145..6ec292e 100644
--- a/core/res/res/drawable-mdpi/btn_default_selected.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_small_normal.9.png b/core/res/res/drawable-mdpi/btn_default_small_normal.9.png
index 5dddd46..0189d0e 100644
--- a/core/res/res/drawable-mdpi/btn_default_small_normal.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_small_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_small_normal_disable.9.png b/core/res/res/drawable-mdpi/btn_default_small_normal_disable.9.png
index 6ab5c4a..067b659 100644
--- a/core/res/res/drawable-mdpi/btn_default_small_normal_disable.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_small_normal_disable.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_small_normal_disable_focused.9.png b/core/res/res/drawable-mdpi/btn_default_small_normal_disable_focused.9.png
index c65bace..381d7b5 100644
--- a/core/res/res/drawable-mdpi/btn_default_small_normal_disable_focused.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_small_normal_disable_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_small_pressed.9.png b/core/res/res/drawable-mdpi/btn_default_small_pressed.9.png
index 43e82f9..b854075 100644
--- a/core/res/res/drawable-mdpi/btn_default_small_pressed.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_small_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_small_selected.9.png b/core/res/res/drawable-mdpi/btn_default_small_selected.9.png
index 7a376a9..fda2ce0 100644
--- a/core/res/res/drawable-mdpi/btn_default_small_selected.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_small_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_transparent_normal.9.png b/core/res/res/drawable-mdpi/btn_default_transparent_normal.9.png
index 3b3dea9..f0746ee5 100644
--- a/core/res/res/drawable-mdpi/btn_default_transparent_normal.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_transparent_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_dialog_disable.png b/core/res/res/drawable-mdpi/btn_dialog_disable.png
index 3de9895..977c23c 100644
--- a/core/res/res/drawable-mdpi/btn_dialog_disable.png
+++ b/core/res/res/drawable-mdpi/btn_dialog_disable.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_dialog_normal.png b/core/res/res/drawable-mdpi/btn_dialog_normal.png
index eca5828..2f35ea0 100644
--- a/core/res/res/drawable-mdpi/btn_dialog_normal.png
+++ b/core/res/res/drawable-mdpi/btn_dialog_normal.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_dialog_pressed.png b/core/res/res/drawable-mdpi/btn_dialog_pressed.png
index f9c4551..2a43999 100644
--- a/core/res/res/drawable-mdpi/btn_dialog_pressed.png
+++ b/core/res/res/drawable-mdpi/btn_dialog_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_dialog_selected.png b/core/res/res/drawable-mdpi/btn_dialog_selected.png
index b0afd7f..68a169a 100644
--- a/core/res/res/drawable-mdpi/btn_dialog_selected.png
+++ b/core/res/res/drawable-mdpi/btn_dialog_selected.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_dropdown_disabled.9.png b/core/res/res/drawable-mdpi/btn_dropdown_disabled.9.png
index 72915b5..3f717db 100644
--- a/core/res/res/drawable-mdpi/btn_dropdown_disabled.9.png
+++ b/core/res/res/drawable-mdpi/btn_dropdown_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_dropdown_disabled_focused.9.png b/core/res/res/drawable-mdpi/btn_dropdown_disabled_focused.9.png
index 438c06a..6026e5c 100644
--- a/core/res/res/drawable-mdpi/btn_dropdown_disabled_focused.9.png
+++ b/core/res/res/drawable-mdpi/btn_dropdown_disabled_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_dropdown_normal.9.png b/core/res/res/drawable-mdpi/btn_dropdown_normal.9.png
index 8540501..5fea98a 100644
--- a/core/res/res/drawable-mdpi/btn_dropdown_normal.9.png
+++ b/core/res/res/drawable-mdpi/btn_dropdown_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_dropdown_pressed.9.png b/core/res/res/drawable-mdpi/btn_dropdown_pressed.9.png
index 9a50396..cf8e84bc 100644
--- a/core/res/res/drawable-mdpi/btn_dropdown_pressed.9.png
+++ b/core/res/res/drawable-mdpi/btn_dropdown_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_dropdown_selected.9.png b/core/res/res/drawable-mdpi/btn_dropdown_selected.9.png
index a0a3fef..1a6a978 100644
--- a/core/res/res/drawable-mdpi/btn_dropdown_selected.9.png
+++ b/core/res/res/drawable-mdpi/btn_dropdown_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_erase_default.9.png b/core/res/res/drawable-mdpi/btn_erase_default.9.png
index c3bf60c..7d86366 100644
--- a/core/res/res/drawable-mdpi/btn_erase_default.9.png
+++ b/core/res/res/drawable-mdpi/btn_erase_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_erase_pressed.9.png b/core/res/res/drawable-mdpi/btn_erase_pressed.9.png
index 727aafe..3f13069 100644
--- a/core/res/res/drawable-mdpi/btn_erase_pressed.9.png
+++ b/core/res/res/drawable-mdpi/btn_erase_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_erase_selected.9.png b/core/res/res/drawable-mdpi/btn_erase_selected.9.png
index c6bd020..1e5236e 100644
--- a/core/res/res/drawable-mdpi/btn_erase_selected.9.png
+++ b/core/res/res/drawable-mdpi/btn_erase_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_global_search_normal.9.png b/core/res/res/drawable-mdpi/btn_global_search_normal.9.png
index 9b7d3e5..b0653ad 100644
--- a/core/res/res/drawable-mdpi/btn_global_search_normal.9.png
+++ b/core/res/res/drawable-mdpi/btn_global_search_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_group_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_group_disabled_holo_dark.9.png
index 5894afe..f742db5 100644
--- a/core/res/res/drawable-mdpi/btn_group_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_group_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_group_disabled_holo_light.9.png b/core/res/res/drawable-mdpi/btn_group_disabled_holo_light.9.png
index 1dfc7d3..71a6101 100644
--- a/core/res/res/drawable-mdpi/btn_group_disabled_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_group_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_group_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_group_focused_holo_dark.9.png
index db2eae1..2d99fbc 100644
--- a/core/res/res/drawable-mdpi/btn_group_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_group_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_group_focused_holo_light.9.png b/core/res/res/drawable-mdpi/btn_group_focused_holo_light.9.png
index db2eae1..2d99fbc 100644
--- a/core/res/res/drawable-mdpi/btn_group_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_group_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_group_normal_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_group_normal_holo_dark.9.png
index c6257bb..c54abcf 100644
--- a/core/res/res/drawable-mdpi/btn_group_normal_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_group_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_group_normal_holo_light.9.png b/core/res/res/drawable-mdpi/btn_group_normal_holo_light.9.png
index 7e25ad3..05273a3 100644
--- a/core/res/res/drawable-mdpi/btn_group_normal_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_group_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_group_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_group_pressed_holo_dark.9.png
index 67b5e4e..48b3a0c 100644
--- a/core/res/res/drawable-mdpi/btn_group_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_group_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_group_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/btn_group_pressed_holo_light.9.png
index 1547267..7c3bcab 100644
--- a/core/res/res/drawable-mdpi/btn_group_pressed_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_group_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_keyboard_key_dark_normal_holo.9.png b/core/res/res/drawable-mdpi/btn_keyboard_key_dark_normal_holo.9.png
index d449d76..22571c5 100644
--- a/core/res/res/drawable-mdpi/btn_keyboard_key_dark_normal_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_keyboard_key_dark_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_keyboard_key_dark_normal_off_holo.9.png b/core/res/res/drawable-mdpi/btn_keyboard_key_dark_normal_off_holo.9.png
index 80fe863..709831d 100644
--- a/core/res/res/drawable-mdpi/btn_keyboard_key_dark_normal_off_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_keyboard_key_dark_normal_off_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_keyboard_key_dark_normal_on_holo.9.png b/core/res/res/drawable-mdpi/btn_keyboard_key_dark_normal_on_holo.9.png
index 196d6d9..f0a149e 100644
--- a/core/res/res/drawable-mdpi/btn_keyboard_key_dark_normal_on_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_keyboard_key_dark_normal_on_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_keyboard_key_dark_pressed_holo.9.png b/core/res/res/drawable-mdpi/btn_keyboard_key_dark_pressed_holo.9.png
index 8f340d3..7d0cbf1 100644
--- a/core/res/res/drawable-mdpi/btn_keyboard_key_dark_pressed_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_keyboard_key_dark_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off_holo.9.png b/core/res/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off_holo.9.png
index b34b957..a61ddef 100644
--- a/core/res/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on_holo.9.png b/core/res/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on_holo.9.png
index 02f4b3d..1301564 100644
--- a/core/res/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_keyboard_key_fulltrans_normal.9.png b/core/res/res/drawable-mdpi/btn_keyboard_key_fulltrans_normal.9.png
index 93767a5..e09ca6d 100644
--- a/core/res/res/drawable-mdpi/btn_keyboard_key_fulltrans_normal.9.png
+++ b/core/res/res/drawable-mdpi/btn_keyboard_key_fulltrans_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_keyboard_key_fulltrans_normal_off.9.png b/core/res/res/drawable-mdpi/btn_keyboard_key_fulltrans_normal_off.9.png
index 7f16a44..3d7312c 100644
--- a/core/res/res/drawable-mdpi/btn_keyboard_key_fulltrans_normal_off.9.png
+++ b/core/res/res/drawable-mdpi/btn_keyboard_key_fulltrans_normal_off.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_keyboard_key_fulltrans_normal_on.9.png b/core/res/res/drawable-mdpi/btn_keyboard_key_fulltrans_normal_on.9.png
index 7887c2e..3ee3880 100644
--- a/core/res/res/drawable-mdpi/btn_keyboard_key_fulltrans_normal_on.9.png
+++ b/core/res/res/drawable-mdpi/btn_keyboard_key_fulltrans_normal_on.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_keyboard_key_fulltrans_pressed.9.png b/core/res/res/drawable-mdpi/btn_keyboard_key_fulltrans_pressed.9.png
index 88dc173..c8cf19b 100644
--- a/core/res/res/drawable-mdpi/btn_keyboard_key_fulltrans_pressed.9.png
+++ b/core/res/res/drawable-mdpi/btn_keyboard_key_fulltrans_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_keyboard_key_fulltrans_pressed_off.9.png b/core/res/res/drawable-mdpi/btn_keyboard_key_fulltrans_pressed_off.9.png
index 9578c09..ea99836 100644
--- a/core/res/res/drawable-mdpi/btn_keyboard_key_fulltrans_pressed_off.9.png
+++ b/core/res/res/drawable-mdpi/btn_keyboard_key_fulltrans_pressed_off.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_keyboard_key_fulltrans_pressed_on.9.png b/core/res/res/drawable-mdpi/btn_keyboard_key_fulltrans_pressed_on.9.png
index 48d2b09..e9a3be7 100644
--- a/core/res/res/drawable-mdpi/btn_keyboard_key_fulltrans_pressed_on.9.png
+++ b/core/res/res/drawable-mdpi/btn_keyboard_key_fulltrans_pressed_on.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_keyboard_key_light_normal_holo.9.png b/core/res/res/drawable-mdpi/btn_keyboard_key_light_normal_holo.9.png
index 976083f..b9deeb9 100644
--- a/core/res/res/drawable-mdpi/btn_keyboard_key_light_normal_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_keyboard_key_light_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_keyboard_key_light_pressed_holo.9.png b/core/res/res/drawable-mdpi/btn_keyboard_key_light_pressed_holo.9.png
index c39dd4a..be052dc 100644
--- a/core/res/res/drawable-mdpi/btn_keyboard_key_light_pressed_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_keyboard_key_light_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_keyboard_key_normal.9.png b/core/res/res/drawable-mdpi/btn_keyboard_key_normal.9.png
index 7ba18dd..a2a55e53a 100644
--- a/core/res/res/drawable-mdpi/btn_keyboard_key_normal.9.png
+++ b/core/res/res/drawable-mdpi/btn_keyboard_key_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_keyboard_key_normal_off.9.png b/core/res/res/drawable-mdpi/btn_keyboard_key_normal_off.9.png
index bda9b83..39e79f9 100644
--- a/core/res/res/drawable-mdpi/btn_keyboard_key_normal_off.9.png
+++ b/core/res/res/drawable-mdpi/btn_keyboard_key_normal_off.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_keyboard_key_normal_on.9.png b/core/res/res/drawable-mdpi/btn_keyboard_key_normal_on.9.png
index 0c16ed5..d1301639 100644
--- a/core/res/res/drawable-mdpi/btn_keyboard_key_normal_on.9.png
+++ b/core/res/res/drawable-mdpi/btn_keyboard_key_normal_on.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_keyboard_key_pressed.9.png b/core/res/res/drawable-mdpi/btn_keyboard_key_pressed.9.png
index 39b9314..38304f6 100644
--- a/core/res/res/drawable-mdpi/btn_keyboard_key_pressed.9.png
+++ b/core/res/res/drawable-mdpi/btn_keyboard_key_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_keyboard_key_pressed_off.9.png b/core/res/res/drawable-mdpi/btn_keyboard_key_pressed_off.9.png
index bdcf06e..2abeac3 100644
--- a/core/res/res/drawable-mdpi/btn_keyboard_key_pressed_off.9.png
+++ b/core/res/res/drawable-mdpi/btn_keyboard_key_pressed_off.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_keyboard_key_pressed_on.9.png b/core/res/res/drawable-mdpi/btn_keyboard_key_pressed_on.9.png
index 79621a9..ac816e9 100644
--- a/core/res/res/drawable-mdpi/btn_keyboard_key_pressed_on.9.png
+++ b/core/res/res/drawable-mdpi/btn_keyboard_key_pressed_on.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_keyboard_key_trans_normal.9.png b/core/res/res/drawable-mdpi/btn_keyboard_key_trans_normal.9.png
index 652c05f..a080f14 100644
--- a/core/res/res/drawable-mdpi/btn_keyboard_key_trans_normal.9.png
+++ b/core/res/res/drawable-mdpi/btn_keyboard_key_trans_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_keyboard_key_trans_normal_off.9.png b/core/res/res/drawable-mdpi/btn_keyboard_key_trans_normal_off.9.png
index 77426ef..f21959e 100644
--- a/core/res/res/drawable-mdpi/btn_keyboard_key_trans_normal_off.9.png
+++ b/core/res/res/drawable-mdpi/btn_keyboard_key_trans_normal_off.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_keyboard_key_trans_normal_on.9.png b/core/res/res/drawable-mdpi/btn_keyboard_key_trans_normal_on.9.png
index e4c9bd5..d4a92a9 100644
--- a/core/res/res/drawable-mdpi/btn_keyboard_key_trans_normal_on.9.png
+++ b/core/res/res/drawable-mdpi/btn_keyboard_key_trans_normal_on.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_keyboard_key_trans_pressed.9.png b/core/res/res/drawable-mdpi/btn_keyboard_key_trans_pressed.9.png
index 1d1e9c0..3bd08ac 100644
--- a/core/res/res/drawable-mdpi/btn_keyboard_key_trans_pressed.9.png
+++ b/core/res/res/drawable-mdpi/btn_keyboard_key_trans_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_keyboard_key_trans_pressed_off.9.png b/core/res/res/drawable-mdpi/btn_keyboard_key_trans_pressed_off.9.png
index bb98b01..6865274 100644
--- a/core/res/res/drawable-mdpi/btn_keyboard_key_trans_pressed_off.9.png
+++ b/core/res/res/drawable-mdpi/btn_keyboard_key_trans_pressed_off.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_keyboard_key_trans_pressed_on.9.png b/core/res/res/drawable-mdpi/btn_keyboard_key_trans_pressed_on.9.png
index 3c7dcc80..fc1f614 100644
--- a/core/res/res/drawable-mdpi/btn_keyboard_key_trans_pressed_on.9.png
+++ b/core/res/res/drawable-mdpi/btn_keyboard_key_trans_pressed_on.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_keyboard_key_trans_selected.9.png b/core/res/res/drawable-mdpi/btn_keyboard_key_trans_selected.9.png
index b168e0c..e471254 100644
--- a/core/res/res/drawable-mdpi/btn_keyboard_key_trans_selected.9.png
+++ b/core/res/res/drawable-mdpi/btn_keyboard_key_trans_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_media_player.9.png b/core/res/res/drawable-mdpi/btn_media_player.9.png
index 3ec3f683..a8ee79d 100644
--- a/core/res/res/drawable-mdpi/btn_media_player.9.png
+++ b/core/res/res/drawable-mdpi/btn_media_player.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_media_player_disabled.9.png b/core/res/res/drawable-mdpi/btn_media_player_disabled.9.png
index e74335b..8cf4c9b 100644
--- a/core/res/res/drawable-mdpi/btn_media_player_disabled.9.png
+++ b/core/res/res/drawable-mdpi/btn_media_player_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_media_player_disabled_selected.9.png b/core/res/res/drawable-mdpi/btn_media_player_disabled_selected.9.png
index 2c6517f..40c8e20 100644
--- a/core/res/res/drawable-mdpi/btn_media_player_disabled_selected.9.png
+++ b/core/res/res/drawable-mdpi/btn_media_player_disabled_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_media_player_pressed.9.png b/core/res/res/drawable-mdpi/btn_media_player_pressed.9.png
index 40bee47..2776f30 100644
--- a/core/res/res/drawable-mdpi/btn_media_player_pressed.9.png
+++ b/core/res/res/drawable-mdpi/btn_media_player_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_media_player_selected.9.png b/core/res/res/drawable-mdpi/btn_media_player_selected.9.png
index 28d809f..f8295d9 100644
--- a/core/res/res/drawable-mdpi/btn_media_player_selected.9.png
+++ b/core/res/res/drawable-mdpi/btn_media_player_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_minus_default.png b/core/res/res/drawable-mdpi/btn_minus_default.png
index ee95879..c7aa13b 100644
--- a/core/res/res/drawable-mdpi/btn_minus_default.png
+++ b/core/res/res/drawable-mdpi/btn_minus_default.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_minus_disable.png b/core/res/res/drawable-mdpi/btn_minus_disable.png
index dff7bf7..a3887d6 100644
--- a/core/res/res/drawable-mdpi/btn_minus_disable.png
+++ b/core/res/res/drawable-mdpi/btn_minus_disable.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_minus_disable_focused.png b/core/res/res/drawable-mdpi/btn_minus_disable_focused.png
index 3f04557..182acd7 100644
--- a/core/res/res/drawable-mdpi/btn_minus_disable_focused.png
+++ b/core/res/res/drawable-mdpi/btn_minus_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_minus_pressed.png b/core/res/res/drawable-mdpi/btn_minus_pressed.png
index 758d958..0db17a6 100644
--- a/core/res/res/drawable-mdpi/btn_minus_pressed.png
+++ b/core/res/res/drawable-mdpi/btn_minus_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_minus_selected.png b/core/res/res/drawable-mdpi/btn_minus_selected.png
index 752a249..d83ae43 100644
--- a/core/res/res/drawable-mdpi/btn_minus_selected.png
+++ b/core/res/res/drawable-mdpi/btn_minus_selected.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_plus_default.png b/core/res/res/drawable-mdpi/btn_plus_default.png
index aa31e37..7dc5f77 100644
--- a/core/res/res/drawable-mdpi/btn_plus_default.png
+++ b/core/res/res/drawable-mdpi/btn_plus_default.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_plus_disable.png b/core/res/res/drawable-mdpi/btn_plus_disable.png
index c373cd3..d98c224 100644
--- a/core/res/res/drawable-mdpi/btn_plus_disable.png
+++ b/core/res/res/drawable-mdpi/btn_plus_disable.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_plus_disable_focused.png b/core/res/res/drawable-mdpi/btn_plus_disable_focused.png
index 8f72a5f..75975ff 100644
--- a/core/res/res/drawable-mdpi/btn_plus_disable_focused.png
+++ b/core/res/res/drawable-mdpi/btn_plus_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_plus_pressed.png b/core/res/res/drawable-mdpi/btn_plus_pressed.png
index 1fb8413..07070ab 100644
--- a/core/res/res/drawable-mdpi/btn_plus_pressed.png
+++ b/core/res/res/drawable-mdpi/btn_plus_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_plus_selected.png b/core/res/res/drawable-mdpi/btn_plus_selected.png
index 47fe9bf..a6feedb0 100644
--- a/core/res/res/drawable-mdpi/btn_plus_selected.png
+++ b/core/res/res/drawable-mdpi/btn_plus_selected.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_label_background.9.png b/core/res/res/drawable-mdpi/btn_radio_label_background.9.png
index 16e8939..88e84be 100644
--- a/core/res/res/drawable-mdpi/btn_radio_label_background.9.png
+++ b/core/res/res/drawable-mdpi/btn_radio_label_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_off.png b/core/res/res/drawable-mdpi/btn_radio_off.png
index ef7130d..908129c 100644
--- a/core/res/res/drawable-mdpi/btn_radio_off.png
+++ b/core/res/res/drawable-mdpi/btn_radio_off.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_off_disabled_focused_holo_dark.png b/core/res/res/drawable-mdpi/btn_radio_off_disabled_focused_holo_dark.png
index 0ad3a31..a66455d 100644
--- a/core/res/res/drawable-mdpi/btn_radio_off_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_radio_off_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_off_disabled_focused_holo_light.png b/core/res/res/drawable-mdpi/btn_radio_off_disabled_focused_holo_light.png
index 4dac84c..bb65865 100644
--- a/core/res/res/drawable-mdpi/btn_radio_off_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_radio_off_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_off_disabled_holo_dark.png b/core/res/res/drawable-mdpi/btn_radio_off_disabled_holo_dark.png
index 20d3d77..25abf85 100644
--- a/core/res/res/drawable-mdpi/btn_radio_off_disabled_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_radio_off_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_off_disabled_holo_light.png b/core/res/res/drawable-mdpi/btn_radio_off_disabled_holo_light.png
index a67375e..256093a 100644
--- a/core/res/res/drawable-mdpi/btn_radio_off_disabled_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_radio_off_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_off_focused_holo_dark.png b/core/res/res/drawable-mdpi/btn_radio_off_focused_holo_dark.png
index 5878db1..c365552 100644
--- a/core/res/res/drawable-mdpi/btn_radio_off_focused_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_radio_off_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_off_focused_holo_light.png b/core/res/res/drawable-mdpi/btn_radio_off_focused_holo_light.png
index 6753d08..38c4a13 100644
--- a/core/res/res/drawable-mdpi/btn_radio_off_focused_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_radio_off_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_off_holo.png b/core/res/res/drawable-mdpi/btn_radio_off_holo.png
index e2077a9..8ada5e6 100644
--- a/core/res/res/drawable-mdpi/btn_radio_off_holo.png
+++ b/core/res/res/drawable-mdpi/btn_radio_off_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_off_holo_dark.png b/core/res/res/drawable-mdpi/btn_radio_off_holo_dark.png
index ac3ef06..e037667 100644
--- a/core/res/res/drawable-mdpi/btn_radio_off_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_radio_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_off_holo_light.png b/core/res/res/drawable-mdpi/btn_radio_off_holo_light.png
index 665cb17..a472953 100644
--- a/core/res/res/drawable-mdpi/btn_radio_off_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_radio_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_off_pressed.png b/core/res/res/drawable-mdpi/btn_radio_off_pressed.png
index f7b77c3..e10ba75 100644
--- a/core/res/res/drawable-mdpi/btn_radio_off_pressed.png
+++ b/core/res/res/drawable-mdpi/btn_radio_off_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_off_pressed_holo_dark.png b/core/res/res/drawable-mdpi/btn_radio_off_pressed_holo_dark.png
index cebaf6d..8f75ce1 100644
--- a/core/res/res/drawable-mdpi/btn_radio_off_pressed_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_radio_off_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_off_pressed_holo_light.png b/core/res/res/drawable-mdpi/btn_radio_off_pressed_holo_light.png
index 7b12bea..209fd3d 100644
--- a/core/res/res/drawable-mdpi/btn_radio_off_pressed_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_radio_off_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_off_selected.png b/core/res/res/drawable-mdpi/btn_radio_off_selected.png
index 5a0d4889..b62b8e7 100644
--- a/core/res/res/drawable-mdpi/btn_radio_off_selected.png
+++ b/core/res/res/drawable-mdpi/btn_radio_off_selected.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_on.png b/core/res/res/drawable-mdpi/btn_radio_on.png
index e13e6396..10477e1 100644
--- a/core/res/res/drawable-mdpi/btn_radio_on.png
+++ b/core/res/res/drawable-mdpi/btn_radio_on.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_on_disabled_focused_holo_dark.png b/core/res/res/drawable-mdpi/btn_radio_on_disabled_focused_holo_dark.png
index 8ffe006..7b6d577 100644
--- a/core/res/res/drawable-mdpi/btn_radio_on_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_radio_on_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_on_disabled_focused_holo_light.png b/core/res/res/drawable-mdpi/btn_radio_on_disabled_focused_holo_light.png
index c9be37e..c0c8148 100644
--- a/core/res/res/drawable-mdpi/btn_radio_on_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_radio_on_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_on_disabled_holo_dark.png b/core/res/res/drawable-mdpi/btn_radio_on_disabled_holo_dark.png
index 605af76..6257a50 100644
--- a/core/res/res/drawable-mdpi/btn_radio_on_disabled_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_radio_on_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_on_disabled_holo_light.png b/core/res/res/drawable-mdpi/btn_radio_on_disabled_holo_light.png
index 4583c3e..ea553b7 100644
--- a/core/res/res/drawable-mdpi/btn_radio_on_disabled_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_radio_on_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_on_focused_holo_dark.png b/core/res/res/drawable-mdpi/btn_radio_on_focused_holo_dark.png
index 456d15d..aa14612a 100644
--- a/core/res/res/drawable-mdpi/btn_radio_on_focused_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_radio_on_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_on_focused_holo_light.png b/core/res/res/drawable-mdpi/btn_radio_on_focused_holo_light.png
index db3b30a..2e0fc65 100644
--- a/core/res/res/drawable-mdpi/btn_radio_on_focused_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_radio_on_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_on_holo.png b/core/res/res/drawable-mdpi/btn_radio_on_holo.png
index 22f9a73..2dd4110 100644
--- a/core/res/res/drawable-mdpi/btn_radio_on_holo.png
+++ b/core/res/res/drawable-mdpi/btn_radio_on_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_on_holo_dark.png b/core/res/res/drawable-mdpi/btn_radio_on_holo_dark.png
index 54674d0..0f98fd2 100644
--- a/core/res/res/drawable-mdpi/btn_radio_on_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_radio_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_on_holo_light.png b/core/res/res/drawable-mdpi/btn_radio_on_holo_light.png
index 917417a..a372374 100644
--- a/core/res/res/drawable-mdpi/btn_radio_on_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_radio_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_on_mtrl_alpha.png b/core/res/res/drawable-mdpi/btn_radio_on_mtrl_alpha.png
index 04a8edb..191889c 100644
--- a/core/res/res/drawable-mdpi/btn_radio_on_mtrl_alpha.png
+++ b/core/res/res/drawable-mdpi/btn_radio_on_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_on_pressed.png b/core/res/res/drawable-mdpi/btn_radio_on_pressed.png
index ae50c20..96670d6 100644
--- a/core/res/res/drawable-mdpi/btn_radio_on_pressed.png
+++ b/core/res/res/drawable-mdpi/btn_radio_on_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_on_pressed_holo_dark.png b/core/res/res/drawable-mdpi/btn_radio_on_pressed_holo_dark.png
index eabb9d2..cfac596 100644
--- a/core/res/res/drawable-mdpi/btn_radio_on_pressed_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_radio_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_on_pressed_holo_light.png b/core/res/res/drawable-mdpi/btn_radio_on_pressed_holo_light.png
index 09592355..1e5f4e2 100644
--- a/core/res/res/drawable-mdpi/btn_radio_on_pressed_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_radio_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_on_pressed_mtrl_alpha.png b/core/res/res/drawable-mdpi/btn_radio_on_pressed_mtrl_alpha.png
index 3c304bf..bbfd6e0 100644
--- a/core/res/res/drawable-mdpi/btn_radio_on_pressed_mtrl_alpha.png
+++ b/core/res/res/drawable-mdpi/btn_radio_on_pressed_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_on_selected.png b/core/res/res/drawable-mdpi/btn_radio_on_selected.png
index 3e704aa..e81f875 100644
--- a/core/res/res/drawable-mdpi/btn_radio_on_selected.png
+++ b/core/res/res/drawable-mdpi/btn_radio_on_selected.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_off_disabled_focused_holo_dark.png b/core/res/res/drawable-mdpi/btn_rating_star_off_disabled_focused_holo_dark.png
index 563f609..2a4e8e1 100644
--- a/core/res/res/drawable-mdpi/btn_rating_star_off_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_rating_star_off_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_off_disabled_focused_holo_light.png b/core/res/res/drawable-mdpi/btn_rating_star_off_disabled_focused_holo_light.png
index 60e4717..262efa26 100644
--- a/core/res/res/drawable-mdpi/btn_rating_star_off_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_rating_star_off_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_off_disabled_holo_dark.png b/core/res/res/drawable-mdpi/btn_rating_star_off_disabled_holo_dark.png
index fa4db4f..32d0bee 100644
--- a/core/res/res/drawable-mdpi/btn_rating_star_off_disabled_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_rating_star_off_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_off_disabled_holo_light.png b/core/res/res/drawable-mdpi/btn_rating_star_off_disabled_holo_light.png
index 73a9d9e..c07daec 100644
--- a/core/res/res/drawable-mdpi/btn_rating_star_off_disabled_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_rating_star_off_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_off_focused_holo_dark.png b/core/res/res/drawable-mdpi/btn_rating_star_off_focused_holo_dark.png
index 790251f..6eeaecd 100644
--- a/core/res/res/drawable-mdpi/btn_rating_star_off_focused_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_rating_star_off_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_off_focused_holo_light.png b/core/res/res/drawable-mdpi/btn_rating_star_off_focused_holo_light.png
index aa4690f..75d0cfb 100644
--- a/core/res/res/drawable-mdpi/btn_rating_star_off_focused_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_rating_star_off_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_off_mtrl_alpha.png b/core/res/res/drawable-mdpi/btn_rating_star_off_mtrl_alpha.png
index d38aed2..e2bc3cc 100644
--- a/core/res/res/drawable-mdpi/btn_rating_star_off_mtrl_alpha.png
+++ b/core/res/res/drawable-mdpi/btn_rating_star_off_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_off_normal.png b/core/res/res/drawable-mdpi/btn_rating_star_off_normal.png
index a99441d..4249f00 100644
--- a/core/res/res/drawable-mdpi/btn_rating_star_off_normal.png
+++ b/core/res/res/drawable-mdpi/btn_rating_star_off_normal.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_off_normal_holo_dark.png b/core/res/res/drawable-mdpi/btn_rating_star_off_normal_holo_dark.png
index c08b5c2..99caece 100644
--- a/core/res/res/drawable-mdpi/btn_rating_star_off_normal_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_rating_star_off_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_off_normal_holo_light.png b/core/res/res/drawable-mdpi/btn_rating_star_off_normal_holo_light.png
index 5f0a748..1c4dde0 100644
--- a/core/res/res/drawable-mdpi/btn_rating_star_off_normal_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_rating_star_off_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_off_pressed.png b/core/res/res/drawable-mdpi/btn_rating_star_off_pressed.png
index f47a4541..f35bed3 100644
--- a/core/res/res/drawable-mdpi/btn_rating_star_off_pressed.png
+++ b/core/res/res/drawable-mdpi/btn_rating_star_off_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_off_pressed_holo_dark.png b/core/res/res/drawable-mdpi/btn_rating_star_off_pressed_holo_dark.png
index ba916c1..8204dba 100644
--- a/core/res/res/drawable-mdpi/btn_rating_star_off_pressed_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_rating_star_off_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_off_pressed_holo_light.png b/core/res/res/drawable-mdpi/btn_rating_star_off_pressed_holo_light.png
index 8d0638d..532d4c7 100644
--- a/core/res/res/drawable-mdpi/btn_rating_star_off_pressed_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_rating_star_off_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_off_selected.png b/core/res/res/drawable-mdpi/btn_rating_star_off_selected.png
index 5f71e08..b6ce53e 100644
--- a/core/res/res/drawable-mdpi/btn_rating_star_off_selected.png
+++ b/core/res/res/drawable-mdpi/btn_rating_star_off_selected.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_on_disabled_focused_holo_dark.png b/core/res/res/drawable-mdpi/btn_rating_star_on_disabled_focused_holo_dark.png
index 9b04c59..d37172d 100644
--- a/core/res/res/drawable-mdpi/btn_rating_star_on_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_rating_star_on_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_on_disabled_focused_holo_light.png b/core/res/res/drawable-mdpi/btn_rating_star_on_disabled_focused_holo_light.png
index 291fdb3..6c47e0d 100644
--- a/core/res/res/drawable-mdpi/btn_rating_star_on_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_rating_star_on_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_on_disabled_holo_dark.png b/core/res/res/drawable-mdpi/btn_rating_star_on_disabled_holo_dark.png
index 5cc6600..874176b 100644
--- a/core/res/res/drawable-mdpi/btn_rating_star_on_disabled_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_rating_star_on_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_on_disabled_holo_light.png b/core/res/res/drawable-mdpi/btn_rating_star_on_disabled_holo_light.png
index f17edca..0679ea2 100644
--- a/core/res/res/drawable-mdpi/btn_rating_star_on_disabled_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_rating_star_on_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_on_focused_holo_dark.png b/core/res/res/drawable-mdpi/btn_rating_star_on_focused_holo_dark.png
index 26f5f11..c6e5140 100644
--- a/core/res/res/drawable-mdpi/btn_rating_star_on_focused_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_rating_star_on_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_on_focused_holo_light.png b/core/res/res/drawable-mdpi/btn_rating_star_on_focused_holo_light.png
index 6346fff..a3951b9 100644
--- a/core/res/res/drawable-mdpi/btn_rating_star_on_focused_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_rating_star_on_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_on_mtrl_alpha.png b/core/res/res/drawable-mdpi/btn_rating_star_on_mtrl_alpha.png
index 87dade3..b4e3543 100644
--- a/core/res/res/drawable-mdpi/btn_rating_star_on_mtrl_alpha.png
+++ b/core/res/res/drawable-mdpi/btn_rating_star_on_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_on_normal.png b/core/res/res/drawable-mdpi/btn_rating_star_on_normal.png
index b7825d3..838adf6 100644
--- a/core/res/res/drawable-mdpi/btn_rating_star_on_normal.png
+++ b/core/res/res/drawable-mdpi/btn_rating_star_on_normal.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_on_normal_holo_dark.png b/core/res/res/drawable-mdpi/btn_rating_star_on_normal_holo_dark.png
index 14bfde7..8c2e19d 100644
--- a/core/res/res/drawable-mdpi/btn_rating_star_on_normal_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_rating_star_on_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_on_normal_holo_light.png b/core/res/res/drawable-mdpi/btn_rating_star_on_normal_holo_light.png
index c5005f1..23e28c5 100644
--- a/core/res/res/drawable-mdpi/btn_rating_star_on_normal_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_rating_star_on_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_on_pressed.png b/core/res/res/drawable-mdpi/btn_rating_star_on_pressed.png
index 4052445..27b8971 100644
--- a/core/res/res/drawable-mdpi/btn_rating_star_on_pressed.png
+++ b/core/res/res/drawable-mdpi/btn_rating_star_on_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_on_pressed_holo_dark.png b/core/res/res/drawable-mdpi/btn_rating_star_on_pressed_holo_dark.png
index 886d86a..624afe6 100644
--- a/core/res/res/drawable-mdpi/btn_rating_star_on_pressed_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_rating_star_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_on_pressed_holo_light.png b/core/res/res/drawable-mdpi/btn_rating_star_on_pressed_holo_light.png
index 9f9eb1d..a5fff57 100644
--- a/core/res/res/drawable-mdpi/btn_rating_star_on_pressed_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_rating_star_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_on_selected.png b/core/res/res/drawable-mdpi/btn_rating_star_on_selected.png
index 5d139b6..822e97b 100644
--- a/core/res/res/drawable-mdpi/btn_rating_star_on_selected.png
+++ b/core/res/res/drawable-mdpi/btn_rating_star_on_selected.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_search_dialog_default.9.png b/core/res/res/drawable-mdpi/btn_search_dialog_default.9.png
index 7275231..55b1df9 100644
--- a/core/res/res/drawable-mdpi/btn_search_dialog_default.9.png
+++ b/core/res/res/drawable-mdpi/btn_search_dialog_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_search_dialog_pressed.9.png b/core/res/res/drawable-mdpi/btn_search_dialog_pressed.9.png
index 50a9209..d9d5796 100644
--- a/core/res/res/drawable-mdpi/btn_search_dialog_pressed.9.png
+++ b/core/res/res/drawable-mdpi/btn_search_dialog_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_search_dialog_selected.9.png b/core/res/res/drawable-mdpi/btn_search_dialog_selected.9.png
index 14b774a..798756c 100644
--- a/core/res/res/drawable-mdpi/btn_search_dialog_selected.9.png
+++ b/core/res/res/drawable-mdpi/btn_search_dialog_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_search_dialog_voice_default.9.png b/core/res/res/drawable-mdpi/btn_search_dialog_voice_default.9.png
index 42be225..17adf13 100644
--- a/core/res/res/drawable-mdpi/btn_search_dialog_voice_default.9.png
+++ b/core/res/res/drawable-mdpi/btn_search_dialog_voice_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_search_dialog_voice_pressed.9.png b/core/res/res/drawable-mdpi/btn_search_dialog_voice_pressed.9.png
index 9984096..c8ecf93 100644
--- a/core/res/res/drawable-mdpi/btn_search_dialog_voice_pressed.9.png
+++ b/core/res/res/drawable-mdpi/btn_search_dialog_voice_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_search_dialog_voice_selected.9.png b/core/res/res/drawable-mdpi/btn_search_dialog_voice_selected.9.png
index de2b030..f2b22eb 100644
--- a/core/res/res/drawable-mdpi/btn_search_dialog_voice_selected.9.png
+++ b/core/res/res/drawable-mdpi/btn_search_dialog_voice_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_square_overlay_disabled.png b/core/res/res/drawable-mdpi/btn_square_overlay_disabled.png
index cf7e4ea..9e41a95 100644
--- a/core/res/res/drawable-mdpi/btn_square_overlay_disabled.png
+++ b/core/res/res/drawable-mdpi/btn_square_overlay_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_square_overlay_disabled_focused.png b/core/res/res/drawable-mdpi/btn_square_overlay_disabled_focused.png
index 5aa1143..ed041b1 100644
--- a/core/res/res/drawable-mdpi/btn_square_overlay_disabled_focused.png
+++ b/core/res/res/drawable-mdpi/btn_square_overlay_disabled_focused.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_square_overlay_normal.png b/core/res/res/drawable-mdpi/btn_square_overlay_normal.png
index 45fa4fe..3634b1b 100644
--- a/core/res/res/drawable-mdpi/btn_square_overlay_normal.png
+++ b/core/res/res/drawable-mdpi/btn_square_overlay_normal.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_square_overlay_pressed.png b/core/res/res/drawable-mdpi/btn_square_overlay_pressed.png
index 952571b..e985bac 100644
--- a/core/res/res/drawable-mdpi/btn_square_overlay_pressed.png
+++ b/core/res/res/drawable-mdpi/btn_square_overlay_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_square_overlay_selected.png b/core/res/res/drawable-mdpi/btn_square_overlay_selected.png
index ce4515e..e300db8 100644
--- a/core/res/res/drawable-mdpi/btn_square_overlay_selected.png
+++ b/core/res/res/drawable-mdpi/btn_square_overlay_selected.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_star_big_off.png b/core/res/res/drawable-mdpi/btn_star_big_off.png
index 7e9342b..7fa6ca7 100644
--- a/core/res/res/drawable-mdpi/btn_star_big_off.png
+++ b/core/res/res/drawable-mdpi/btn_star_big_off.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_star_big_off_disable.png b/core/res/res/drawable-mdpi/btn_star_big_off_disable.png
index 066d920..9f4dc1e 100644
--- a/core/res/res/drawable-mdpi/btn_star_big_off_disable.png
+++ b/core/res/res/drawable-mdpi/btn_star_big_off_disable.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_star_big_off_disable_focused.png b/core/res/res/drawable-mdpi/btn_star_big_off_disable_focused.png
index 1855d2c..7c96713 100644
--- a/core/res/res/drawable-mdpi/btn_star_big_off_disable_focused.png
+++ b/core/res/res/drawable-mdpi/btn_star_big_off_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_star_big_off_pressed.png b/core/res/res/drawable-mdpi/btn_star_big_off_pressed.png
index f1b8912..77f7e81 100644
--- a/core/res/res/drawable-mdpi/btn_star_big_off_pressed.png
+++ b/core/res/res/drawable-mdpi/btn_star_big_off_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_star_big_off_selected.png b/core/res/res/drawable-mdpi/btn_star_big_off_selected.png
index 0be64c4..cbf0ec9 100644
--- a/core/res/res/drawable-mdpi/btn_star_big_off_selected.png
+++ b/core/res/res/drawable-mdpi/btn_star_big_off_selected.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_star_big_on.png b/core/res/res/drawable-mdpi/btn_star_big_on.png
index a9bdb05..9aa377a 100644
--- a/core/res/res/drawable-mdpi/btn_star_big_on.png
+++ b/core/res/res/drawable-mdpi/btn_star_big_on.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_star_big_on_disable.png b/core/res/res/drawable-mdpi/btn_star_big_on_disable.png
index 5e65a2f..b6cef32 100644
--- a/core/res/res/drawable-mdpi/btn_star_big_on_disable.png
+++ b/core/res/res/drawable-mdpi/btn_star_big_on_disable.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_star_big_on_disable_focused.png b/core/res/res/drawable-mdpi/btn_star_big_on_disable_focused.png
index de57571..c895810 100644
--- a/core/res/res/drawable-mdpi/btn_star_big_on_disable_focused.png
+++ b/core/res/res/drawable-mdpi/btn_star_big_on_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_star_big_on_pressed.png b/core/res/res/drawable-mdpi/btn_star_big_on_pressed.png
index 159a84b..4fcb4b7 100644
--- a/core/res/res/drawable-mdpi/btn_star_big_on_pressed.png
+++ b/core/res/res/drawable-mdpi/btn_star_big_on_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_star_big_on_selected.png b/core/res/res/drawable-mdpi/btn_star_big_on_selected.png
index 0592d51..fb0420c 100644
--- a/core/res/res/drawable-mdpi/btn_star_big_on_selected.png
+++ b/core/res/res/drawable-mdpi/btn_star_big_on_selected.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_star_label_background.9.png b/core/res/res/drawable-mdpi/btn_star_label_background.9.png
index e493171..313915f 100644
--- a/core/res/res/drawable-mdpi/btn_star_label_background.9.png
+++ b/core/res/res/drawable-mdpi/btn_star_label_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_star_mtrl_alpha.png b/core/res/res/drawable-mdpi/btn_star_mtrl_alpha.png
index 7ce950d..11c8aad 100644
--- a/core/res/res/drawable-mdpi/btn_star_mtrl_alpha.png
+++ b/core/res/res/drawable-mdpi/btn_star_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_star_off_disabled_focused_holo_dark.png b/core/res/res/drawable-mdpi/btn_star_off_disabled_focused_holo_dark.png
index 690371d..17b42c5 100644
--- a/core/res/res/drawable-mdpi/btn_star_off_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_star_off_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_star_off_disabled_focused_holo_light.png b/core/res/res/drawable-mdpi/btn_star_off_disabled_focused_holo_light.png
index 6d026dc..88b9a20 100644
--- a/core/res/res/drawable-mdpi/btn_star_off_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_star_off_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_star_off_disabled_holo_dark.png b/core/res/res/drawable-mdpi/btn_star_off_disabled_holo_dark.png
index 6e368d6..d6ecb7c 100644
--- a/core/res/res/drawable-mdpi/btn_star_off_disabled_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_star_off_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_star_off_disabled_holo_light.png b/core/res/res/drawable-mdpi/btn_star_off_disabled_holo_light.png
index 71cb582..b4fde0c 100644
--- a/core/res/res/drawable-mdpi/btn_star_off_disabled_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_star_off_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_star_off_focused_holo_dark.png b/core/res/res/drawable-mdpi/btn_star_off_focused_holo_dark.png
index ebc9914..de984a1 100644
--- a/core/res/res/drawable-mdpi/btn_star_off_focused_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_star_off_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_star_off_focused_holo_light.png b/core/res/res/drawable-mdpi/btn_star_off_focused_holo_light.png
index edc3399..d164a79 100644
--- a/core/res/res/drawable-mdpi/btn_star_off_focused_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_star_off_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_star_off_normal_holo_dark.png b/core/res/res/drawable-mdpi/btn_star_off_normal_holo_dark.png
index 7dc8089..8bea1dd 100644
--- a/core/res/res/drawable-mdpi/btn_star_off_normal_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_star_off_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_star_off_normal_holo_light.png b/core/res/res/drawable-mdpi/btn_star_off_normal_holo_light.png
index a9abdc0..af540c5 100644
--- a/core/res/res/drawable-mdpi/btn_star_off_normal_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_star_off_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_star_off_pressed_holo_dark.png b/core/res/res/drawable-mdpi/btn_star_off_pressed_holo_dark.png
index 360ce61..9ca5f82e 100644
--- a/core/res/res/drawable-mdpi/btn_star_off_pressed_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_star_off_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_star_off_pressed_holo_light.png b/core/res/res/drawable-mdpi/btn_star_off_pressed_holo_light.png
index 4884309..9a550b5 100644
--- a/core/res/res/drawable-mdpi/btn_star_off_pressed_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_star_off_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_star_on_disabled_focused_holo_dark.png b/core/res/res/drawable-mdpi/btn_star_on_disabled_focused_holo_dark.png
index 3b5901f..268d271 100644
--- a/core/res/res/drawable-mdpi/btn_star_on_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_star_on_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_star_on_disabled_focused_holo_light.png b/core/res/res/drawable-mdpi/btn_star_on_disabled_focused_holo_light.png
index d61bf39..89e1d6b 100644
--- a/core/res/res/drawable-mdpi/btn_star_on_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_star_on_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_star_on_disabled_holo_dark.png b/core/res/res/drawable-mdpi/btn_star_on_disabled_holo_dark.png
index ff9f8881..0692f36 100644
--- a/core/res/res/drawable-mdpi/btn_star_on_disabled_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_star_on_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_star_on_disabled_holo_light.png b/core/res/res/drawable-mdpi/btn_star_on_disabled_holo_light.png
index 0aa36fe..cdd1976 100644
--- a/core/res/res/drawable-mdpi/btn_star_on_disabled_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_star_on_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_star_on_focused_holo_dark.png b/core/res/res/drawable-mdpi/btn_star_on_focused_holo_dark.png
index fdd1e95..d271979 100644
--- a/core/res/res/drawable-mdpi/btn_star_on_focused_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_star_on_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_star_on_focused_holo_light.png b/core/res/res/drawable-mdpi/btn_star_on_focused_holo_light.png
index 15c9334..38beb21 100644
--- a/core/res/res/drawable-mdpi/btn_star_on_focused_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_star_on_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_star_on_normal_holo_dark.png b/core/res/res/drawable-mdpi/btn_star_on_normal_holo_dark.png
index 14183171..256ae53 100644
--- a/core/res/res/drawable-mdpi/btn_star_on_normal_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_star_on_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_star_on_normal_holo_light.png b/core/res/res/drawable-mdpi/btn_star_on_normal_holo_light.png
index 2e81887..ba4ffd8 100644
--- a/core/res/res/drawable-mdpi/btn_star_on_normal_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_star_on_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_star_on_pressed_holo_dark.png b/core/res/res/drawable-mdpi/btn_star_on_pressed_holo_dark.png
index 9083aec..2cd3317 100644
--- a/core/res/res/drawable-mdpi/btn_star_on_pressed_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_star_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_star_on_pressed_holo_light.png b/core/res/res/drawable-mdpi/btn_star_on_pressed_holo_light.png
index b5f0542d..a7b8699 100644
--- a/core/res/res/drawable-mdpi/btn_star_on_pressed_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_star_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00001.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00001.9.png
index 36ed954..9c6162e 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00001.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00002.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00002.9.png
index 863eee1..cfd6af3 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00002.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00003.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00003.9.png
index 63e93a8..3cc3e1a 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00003.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00004.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00004.9.png
index 85c851d..caff413 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00004.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00005.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00005.9.png
index 8637636..ec4e07c 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00005.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00006.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00006.9.png
index 2945c29..c0d279d2 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00006.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00007.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00007.9.png
index 678a6c8..41d5ce4 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00007.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00008.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00008.9.png
index 238a6f1..09b4fdc 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00008.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00009.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00009.9.png
index 4a342a6..02bb1ee 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00009.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00010.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00010.9.png
index 5842b19..5af207c 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00010.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00011.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00011.9.png
index 3e1bd2d..2cebe6f 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00011.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00012.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00012.9.png
index 73ed10b..ecefbef 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00012.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00001.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00001.9.png
index 03d3dfb..4535fb8 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00001.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00002.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00002.9.png
index 25085ce..fe5eee9 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00002.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00003.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00003.9.png
index 9e4d2f3..faf03dc 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00003.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00004.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00004.9.png
index ab5bd1e..ed7cbba 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00004.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00005.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00005.9.png
index f5297ce..7c66ca3 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00005.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00006.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00006.9.png
index 1ad56e9..cee8ed5 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00006.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00007.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00007.9.png
index 4bad055..41d5ce4 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00007.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00008.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00008.9.png
index d908034..ecc3e4d 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00008.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00009.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00009.9.png
index 8ed4fb4..640f6e3 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00009.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00010.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00010.9.png
index 61d3ced..91c50be 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00010.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00011.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00011.9.png
index dec2a82..8408ff4 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00011.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00012.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00012.9.png
index 6635830..72ff93c 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00012.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off.9.png b/core/res/res/drawable-mdpi/btn_toggle_off.9.png
index 38e810c..11a4fee 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_off.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_off.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_disabled_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_disabled_focused_holo_dark.9.png
index 4e6d076..ac5f0cf 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_off_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_disabled_focused_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_disabled_focused_holo_light.9.png
index 4e6d076..ac5f0cf 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_off_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_disabled_holo_dark.9.png
index ca61cb2..bbf4d5b 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_off_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_disabled_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_disabled_holo_light.9.png
index ca61cb2..bbf4d5b 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_off_disabled_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_focused_holo_dark.9.png
index b5999be..76944cc 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_off_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_focused_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_focused_holo_light.9.png
index b5999be..76944cc 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_off_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_normal_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_normal_holo_dark.9.png
index 8392ac3..8f96363 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_off_normal_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_normal_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_normal_holo_light.9.png
index 522bafd..ccd7978 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_off_normal_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_pressed_holo_dark.9.png
index 626a605..8745f36 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_off_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_pressed_holo_light.9.png
index 196c650..834410a 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_off_pressed_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on.9.png b/core/res/res/drawable-mdpi/btn_toggle_on.9.png
index ef39dec..6235fcf 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_on.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_on.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_disabled_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_disabled_focused_holo_dark.9.png
index ebb2f8b..d08a4e7 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_on_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_disabled_focused_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_disabled_focused_holo_light.9.png
index ebb2f8b..d08a4e7 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_on_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_disabled_holo_dark.9.png
index 3fa20ca..ced29be 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_on_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_disabled_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_disabled_holo_light.9.png
index 3fa20ca..ced29be 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_on_disabled_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_focused_holo_dark.9.png
index 6cc59ed..74cd3cb 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_on_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_focused_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_focused_holo_light.9.png
index 6cc59ed..74cd3cb 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_on_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_normal_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_normal_holo_dark.9.png
index a1fcd08..d4cf1d3 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_on_normal_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_normal_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_normal_holo_light.9.png
index c6c0224..1b66429 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_on_normal_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_pressed_holo_dark.9.png
index 0536053..8423615 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_on_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_pressed_holo_light.9.png
index 9fc345b8..f8dcdb4 100644
--- a/core/res/res/drawable-mdpi/btn_toggle_on_pressed_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_zoom_down_disabled.9.png b/core/res/res/drawable-mdpi/btn_zoom_down_disabled.9.png
index 7780bd7..d364f28 100644
--- a/core/res/res/drawable-mdpi/btn_zoom_down_disabled.9.png
+++ b/core/res/res/drawable-mdpi/btn_zoom_down_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_zoom_down_disabled_focused.9.png b/core/res/res/drawable-mdpi/btn_zoom_down_disabled_focused.9.png
index 39131c5..f8961b5 100644
--- a/core/res/res/drawable-mdpi/btn_zoom_down_disabled_focused.9.png
+++ b/core/res/res/drawable-mdpi/btn_zoom_down_disabled_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_zoom_down_normal.9.png b/core/res/res/drawable-mdpi/btn_zoom_down_normal.9.png
index b589a84..6ca7453 100644
--- a/core/res/res/drawable-mdpi/btn_zoom_down_normal.9.png
+++ b/core/res/res/drawable-mdpi/btn_zoom_down_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_zoom_down_pressed.9.png b/core/res/res/drawable-mdpi/btn_zoom_down_pressed.9.png
index a8ca467..f27ad5d 100644
--- a/core/res/res/drawable-mdpi/btn_zoom_down_pressed.9.png
+++ b/core/res/res/drawable-mdpi/btn_zoom_down_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_zoom_down_selected.9.png b/core/res/res/drawable-mdpi/btn_zoom_down_selected.9.png
index af551e7..4a34449 100644
--- a/core/res/res/drawable-mdpi/btn_zoom_down_selected.9.png
+++ b/core/res/res/drawable-mdpi/btn_zoom_down_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_zoom_page_normal.png b/core/res/res/drawable-mdpi/btn_zoom_page_normal.png
index 839915b..84afe89 100644
--- a/core/res/res/drawable-mdpi/btn_zoom_page_normal.png
+++ b/core/res/res/drawable-mdpi/btn_zoom_page_normal.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_zoom_page_press.png b/core/res/res/drawable-mdpi/btn_zoom_page_press.png
index e8af276..09343be 100644
--- a/core/res/res/drawable-mdpi/btn_zoom_page_press.png
+++ b/core/res/res/drawable-mdpi/btn_zoom_page_press.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_zoom_up_disabled.9.png b/core/res/res/drawable-mdpi/btn_zoom_up_disabled.9.png
index 5203630..883d2a4 100644
--- a/core/res/res/drawable-mdpi/btn_zoom_up_disabled.9.png
+++ b/core/res/res/drawable-mdpi/btn_zoom_up_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_zoom_up_disabled_focused.9.png b/core/res/res/drawable-mdpi/btn_zoom_up_disabled_focused.9.png
index c72c9cd..6c1d86b 100644
--- a/core/res/res/drawable-mdpi/btn_zoom_up_disabled_focused.9.png
+++ b/core/res/res/drawable-mdpi/btn_zoom_up_disabled_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_zoom_up_normal.9.png b/core/res/res/drawable-mdpi/btn_zoom_up_normal.9.png
index 5027348..be41269 100644
--- a/core/res/res/drawable-mdpi/btn_zoom_up_normal.9.png
+++ b/core/res/res/drawable-mdpi/btn_zoom_up_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_zoom_up_pressed.9.png b/core/res/res/drawable-mdpi/btn_zoom_up_pressed.9.png
index 1a93e3a..34f1de1 100644
--- a/core/res/res/drawable-mdpi/btn_zoom_up_pressed.9.png
+++ b/core/res/res/drawable-mdpi/btn_zoom_up_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_zoom_up_selected.9.png b/core/res/res/drawable-mdpi/btn_zoom_up_selected.9.png
index 26aafee..542dedb 100644
--- a/core/res/res/drawable-mdpi/btn_zoom_up_selected.9.png
+++ b/core/res/res/drawable-mdpi/btn_zoom_up_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/button_onoff_indicator_off.png b/core/res/res/drawable-mdpi/button_onoff_indicator_off.png
index 91e7244..6ccb197 100644
--- a/core/res/res/drawable-mdpi/button_onoff_indicator_off.png
+++ b/core/res/res/drawable-mdpi/button_onoff_indicator_off.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/button_onoff_indicator_on.png b/core/res/res/drawable-mdpi/button_onoff_indicator_on.png
index 361364b..e5ac85d 100644
--- a/core/res/res/drawable-mdpi/button_onoff_indicator_on.png
+++ b/core/res/res/drawable-mdpi/button_onoff_indicator_on.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/cab_background_bottom_mtrl_alpha.9.png b/core/res/res/drawable-mdpi/cab_background_bottom_mtrl_alpha.9.png
index df292a0..81d30b0 100644
--- a/core/res/res/drawable-mdpi/cab_background_bottom_mtrl_alpha.9.png
+++ b/core/res/res/drawable-mdpi/cab_background_bottom_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/cab_background_top_holo_dark.9.png b/core/res/res/drawable-mdpi/cab_background_top_holo_dark.9.png
index 7c2cbe5..0761dd7 100644
--- a/core/res/res/drawable-mdpi/cab_background_top_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/cab_background_top_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/cab_background_top_holo_light.9.png b/core/res/res/drawable-mdpi/cab_background_top_holo_light.9.png
index 30cbdc1..36193db 100644
--- a/core/res/res/drawable-mdpi/cab_background_top_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/cab_background_top_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/cab_background_top_mtrl_alpha.9.png b/core/res/res/drawable-mdpi/cab_background_top_mtrl_alpha.9.png
index ae8cccd..1f13e39 100644
--- a/core/res/res/drawable-mdpi/cab_background_top_mtrl_alpha.9.png
+++ b/core/res/res/drawable-mdpi/cab_background_top_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/call_contact.png b/core/res/res/drawable-mdpi/call_contact.png
index 1abeb5d..0855ab3 100644
--- a/core/res/res/drawable-mdpi/call_contact.png
+++ b/core/res/res/drawable-mdpi/call_contact.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/checkbox_off_background.png b/core/res/res/drawable-mdpi/checkbox_off_background.png
index 825ea66..2f25e79 100644
--- a/core/res/res/drawable-mdpi/checkbox_off_background.png
+++ b/core/res/res/drawable-mdpi/checkbox_off_background.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/checkbox_on_background.png b/core/res/res/drawable-mdpi/checkbox_on_background.png
index 57585da..00de55c 100644
--- a/core/res/res/drawable-mdpi/checkbox_on_background.png
+++ b/core/res/res/drawable-mdpi/checkbox_on_background.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/cling_arrow_up.png b/core/res/res/drawable-mdpi/cling_arrow_up.png
index ee6c378..38c4f47 100644
--- a/core/res/res/drawable-mdpi/cling_arrow_up.png
+++ b/core/res/res/drawable-mdpi/cling_arrow_up.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/cling_bg.9.png b/core/res/res/drawable-mdpi/cling_bg.9.png
index 4c0f139..e54e621 100644
--- a/core/res/res/drawable-mdpi/cling_bg.9.png
+++ b/core/res/res/drawable-mdpi/cling_bg.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/cling_button_normal.9.png b/core/res/res/drawable-mdpi/cling_button_normal.9.png
index a0b6f97..c278a98 100644
--- a/core/res/res/drawable-mdpi/cling_button_normal.9.png
+++ b/core/res/res/drawable-mdpi/cling_button_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/cling_button_pressed.9.png b/core/res/res/drawable-mdpi/cling_button_pressed.9.png
index 986e669..5d29d97 100644
--- a/core/res/res/drawable-mdpi/cling_button_pressed.9.png
+++ b/core/res/res/drawable-mdpi/cling_button_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/code_lock_bottom.9.png b/core/res/res/drawable-mdpi/code_lock_bottom.9.png
index 812cf00..9c2b258 100644
--- a/core/res/res/drawable-mdpi/code_lock_bottom.9.png
+++ b/core/res/res/drawable-mdpi/code_lock_bottom.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/code_lock_left.9.png b/core/res/res/drawable-mdpi/code_lock_left.9.png
index 215dcc8..5c502ad 100644
--- a/core/res/res/drawable-mdpi/code_lock_left.9.png
+++ b/core/res/res/drawable-mdpi/code_lock_left.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/code_lock_top.9.png b/core/res/res/drawable-mdpi/code_lock_top.9.png
index 2b75a7c..cbdbe5e 100644
--- a/core/res/res/drawable-mdpi/code_lock_top.9.png
+++ b/core/res/res/drawable-mdpi/code_lock_top.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/combobox_disabled.png b/core/res/res/drawable-mdpi/combobox_disabled.png
index ac8a235..f04a11e 100644
--- a/core/res/res/drawable-mdpi/combobox_disabled.png
+++ b/core/res/res/drawable-mdpi/combobox_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/combobox_nohighlight.png b/core/res/res/drawable-mdpi/combobox_nohighlight.png
index 9d60e26..df73a86 100644
--- a/core/res/res/drawable-mdpi/combobox_nohighlight.png
+++ b/core/res/res/drawable-mdpi/combobox_nohighlight.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/compass_arrow.png b/core/res/res/drawable-mdpi/compass_arrow.png
index 5a4d8c1..e7d54ae 100644
--- a/core/res/res/drawable-mdpi/compass_arrow.png
+++ b/core/res/res/drawable-mdpi/compass_arrow.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/compass_base.png b/core/res/res/drawable-mdpi/compass_base.png
index 3d694f0..ed439a4 100644
--- a/core/res/res/drawable-mdpi/compass_base.png
+++ b/core/res/res/drawable-mdpi/compass_base.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/contact_header_bg.9.png b/core/res/res/drawable-mdpi/contact_header_bg.9.png
index 7f9a5a3..73580188 100644
--- a/core/res/res/drawable-mdpi/contact_header_bg.9.png
+++ b/core/res/res/drawable-mdpi/contact_header_bg.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/create_contact.png b/core/res/res/drawable-mdpi/create_contact.png
index 5a9360b..0d06374 100644
--- a/core/res/res/drawable-mdpi/create_contact.png
+++ b/core/res/res/drawable-mdpi/create_contact.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dark_header.9.png b/core/res/res/drawable-mdpi/dark_header.9.png
index ac906cd..d64f27a 100644
--- a/core/res/res/drawable-mdpi/dark_header.9.png
+++ b/core/res/res/drawable-mdpi/dark_header.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/day_picker_week_view_dayline_holo.9.png b/core/res/res/drawable-mdpi/day_picker_week_view_dayline_holo.9.png
index 7b75019..aec11cf 100644
--- a/core/res/res/drawable-mdpi/day_picker_week_view_dayline_holo.9.png
+++ b/core/res/res/drawable-mdpi/day_picker_week_view_dayline_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_bottom_holo_dark.9.png b/core/res/res/drawable-mdpi/dialog_bottom_holo_dark.9.png
index 31dc4fd..142ccb9 100644
--- a/core/res/res/drawable-mdpi/dialog_bottom_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/dialog_bottom_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_bottom_holo_light.9.png b/core/res/res/drawable-mdpi/dialog_bottom_holo_light.9.png
index 7541e8a..c974f29 100644
--- a/core/res/res/drawable-mdpi/dialog_bottom_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/dialog_bottom_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_divider_horizontal_holo_dark.9.png b/core/res/res/drawable-mdpi/dialog_divider_horizontal_holo_dark.9.png
index 1851468..804fe51 100644
--- a/core/res/res/drawable-mdpi/dialog_divider_horizontal_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/dialog_divider_horizontal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_divider_horizontal_holo_light.9.png b/core/res/res/drawable-mdpi/dialog_divider_horizontal_holo_light.9.png
index a60aad5..fee85e7 100644
--- a/core/res/res/drawable-mdpi/dialog_divider_horizontal_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/dialog_divider_horizontal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_divider_horizontal_light.9.png b/core/res/res/drawable-mdpi/dialog_divider_horizontal_light.9.png
index b69619b..d7f0904 100644
--- a/core/res/res/drawable-mdpi/dialog_divider_horizontal_light.9.png
+++ b/core/res/res/drawable-mdpi/dialog_divider_horizontal_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_full_holo_dark.9.png b/core/res/res/drawable-mdpi/dialog_full_holo_dark.9.png
index dc37316..024b999 100644
--- a/core/res/res/drawable-mdpi/dialog_full_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/dialog_full_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_full_holo_light.9.png b/core/res/res/drawable-mdpi/dialog_full_holo_light.9.png
index 0c5770a..546681b 100644
--- a/core/res/res/drawable-mdpi/dialog_full_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/dialog_full_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_ic_close_focused_holo_dark.png b/core/res/res/drawable-mdpi/dialog_ic_close_focused_holo_dark.png
index cc5f4f4..da49d64 100644
--- a/core/res/res/drawable-mdpi/dialog_ic_close_focused_holo_dark.png
+++ b/core/res/res/drawable-mdpi/dialog_ic_close_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_ic_close_focused_holo_light.png b/core/res/res/drawable-mdpi/dialog_ic_close_focused_holo_light.png
index 51b4e4d..ddd67dd 100644
--- a/core/res/res/drawable-mdpi/dialog_ic_close_focused_holo_light.png
+++ b/core/res/res/drawable-mdpi/dialog_ic_close_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_ic_close_normal_holo_dark.png b/core/res/res/drawable-mdpi/dialog_ic_close_normal_holo_dark.png
index 503db7c..06d2182 100644
--- a/core/res/res/drawable-mdpi/dialog_ic_close_normal_holo_dark.png
+++ b/core/res/res/drawable-mdpi/dialog_ic_close_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_ic_close_normal_holo_light.png b/core/res/res/drawable-mdpi/dialog_ic_close_normal_holo_light.png
index 6a2fb5e..09738e0 100644
--- a/core/res/res/drawable-mdpi/dialog_ic_close_normal_holo_light.png
+++ b/core/res/res/drawable-mdpi/dialog_ic_close_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_ic_close_pressed_holo_dark.png b/core/res/res/drawable-mdpi/dialog_ic_close_pressed_holo_dark.png
index 3463b66..deab903 100644
--- a/core/res/res/drawable-mdpi/dialog_ic_close_pressed_holo_dark.png
+++ b/core/res/res/drawable-mdpi/dialog_ic_close_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_ic_close_pressed_holo_light.png b/core/res/res/drawable-mdpi/dialog_ic_close_pressed_holo_light.png
index 55dedc6..b6001a2 100644
--- a/core/res/res/drawable-mdpi/dialog_ic_close_pressed_holo_light.png
+++ b/core/res/res/drawable-mdpi/dialog_ic_close_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_middle_holo.9.png b/core/res/res/drawable-mdpi/dialog_middle_holo.9.png
index 36da5ca..55386f5 100644
--- a/core/res/res/drawable-mdpi/dialog_middle_holo.9.png
+++ b/core/res/res/drawable-mdpi/dialog_middle_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_middle_holo_dark.9.png b/core/res/res/drawable-mdpi/dialog_middle_holo_dark.9.png
index ca389e3..762be16 100644
--- a/core/res/res/drawable-mdpi/dialog_middle_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/dialog_middle_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_middle_holo_light.9.png b/core/res/res/drawable-mdpi/dialog_middle_holo_light.9.png
index 7a836ce..3d5bb5c 100644
--- a/core/res/res/drawable-mdpi/dialog_middle_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/dialog_middle_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_top_holo_dark.9.png b/core/res/res/drawable-mdpi/dialog_top_holo_dark.9.png
index fb848a3..781da5d 100644
--- a/core/res/res/drawable-mdpi/dialog_top_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/dialog_top_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_top_holo_light.9.png b/core/res/res/drawable-mdpi/dialog_top_holo_light.9.png
index 2ddcab1..2e42078 100644
--- a/core/res/res/drawable-mdpi/dialog_top_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/dialog_top_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/divider_horizontal_bright.9.png b/core/res/res/drawable-mdpi/divider_horizontal_bright.9.png
index 41b776b..f355428 100644
--- a/core/res/res/drawable-mdpi/divider_horizontal_bright.9.png
+++ b/core/res/res/drawable-mdpi/divider_horizontal_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/divider_horizontal_bright_opaque.9.png b/core/res/res/drawable-mdpi/divider_horizontal_bright_opaque.9.png
index eb75a22..72909ae 100644
--- a/core/res/res/drawable-mdpi/divider_horizontal_bright_opaque.9.png
+++ b/core/res/res/drawable-mdpi/divider_horizontal_bright_opaque.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/divider_horizontal_dark.9.png b/core/res/res/drawable-mdpi/divider_horizontal_dark.9.png
index 55a5e53..87769d6 100644
--- a/core/res/res/drawable-mdpi/divider_horizontal_dark.9.png
+++ b/core/res/res/drawable-mdpi/divider_horizontal_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/divider_horizontal_dark_opaque.9.png b/core/res/res/drawable-mdpi/divider_horizontal_dark_opaque.9.png
index 60e2cb2..7e34600 100644
--- a/core/res/res/drawable-mdpi/divider_horizontal_dark_opaque.9.png
+++ b/core/res/res/drawable-mdpi/divider_horizontal_dark_opaque.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/divider_horizontal_dim_dark.9.png b/core/res/res/drawable-mdpi/divider_horizontal_dim_dark.9.png
index cf34613..91c18c1 100644
--- a/core/res/res/drawable-mdpi/divider_horizontal_dim_dark.9.png
+++ b/core/res/res/drawable-mdpi/divider_horizontal_dim_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/divider_horizontal_holo_dark.9.png b/core/res/res/drawable-mdpi/divider_horizontal_holo_dark.9.png
index d6548c6..07972a4 100644
--- a/core/res/res/drawable-mdpi/divider_horizontal_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/divider_horizontal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/divider_horizontal_holo_light.9.png b/core/res/res/drawable-mdpi/divider_horizontal_holo_light.9.png
index 9a42dd2..b1c0334 100644
--- a/core/res/res/drawable-mdpi/divider_horizontal_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/divider_horizontal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/divider_horizontal_textfield.9.png b/core/res/res/drawable-mdpi/divider_horizontal_textfield.9.png
index 43eb51d..ef519e4 100644
--- a/core/res/res/drawable-mdpi/divider_horizontal_textfield.9.png
+++ b/core/res/res/drawable-mdpi/divider_horizontal_textfield.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/divider_strong_holo.9.png b/core/res/res/drawable-mdpi/divider_strong_holo.9.png
index 0758593..f107df4 100644
--- a/core/res/res/drawable-mdpi/divider_strong_holo.9.png
+++ b/core/res/res/drawable-mdpi/divider_strong_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/divider_vertical_bright.9.png b/core/res/res/drawable-mdpi/divider_vertical_bright.9.png
index 41b776b..f355428 100644
--- a/core/res/res/drawable-mdpi/divider_vertical_bright.9.png
+++ b/core/res/res/drawable-mdpi/divider_vertical_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/divider_vertical_bright_opaque.9.png b/core/res/res/drawable-mdpi/divider_vertical_bright_opaque.9.png
index eb75a22..72909ae 100644
--- a/core/res/res/drawable-mdpi/divider_vertical_bright_opaque.9.png
+++ b/core/res/res/drawable-mdpi/divider_vertical_bright_opaque.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/divider_vertical_dark.9.png b/core/res/res/drawable-mdpi/divider_vertical_dark.9.png
index 55a5e53..87769d6 100644
--- a/core/res/res/drawable-mdpi/divider_vertical_dark.9.png
+++ b/core/res/res/drawable-mdpi/divider_vertical_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/divider_vertical_dark_opaque.9.png b/core/res/res/drawable-mdpi/divider_vertical_dark_opaque.9.png
index 60e2cb2..7e34600 100644
--- a/core/res/res/drawable-mdpi/divider_vertical_dark_opaque.9.png
+++ b/core/res/res/drawable-mdpi/divider_vertical_dark_opaque.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/divider_vertical_holo_dark.9.png b/core/res/res/drawable-mdpi/divider_vertical_holo_dark.9.png
index c039428..7e28b00 100644
--- a/core/res/res/drawable-mdpi/divider_vertical_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/divider_vertical_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/divider_vertical_holo_light.9.png b/core/res/res/drawable-mdpi/divider_vertical_holo_light.9.png
index 7c4a29f..2dc0ba4 100644
--- a/core/res/res/drawable-mdpi/divider_vertical_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/divider_vertical_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dropdown_disabled_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/dropdown_disabled_focused_holo_dark.9.png
index bc6636c..0fb5d5f 100644
--- a/core/res/res/drawable-mdpi/dropdown_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/dropdown_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dropdown_disabled_focused_holo_light.9.png b/core/res/res/drawable-mdpi/dropdown_disabled_focused_holo_light.9.png
index 7f9a9f1..e66c632a 100644
--- a/core/res/res/drawable-mdpi/dropdown_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/dropdown_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dropdown_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/dropdown_disabled_holo_dark.9.png
index 6af742a..5a009f92 100644
--- a/core/res/res/drawable-mdpi/dropdown_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/dropdown_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dropdown_disabled_holo_light.9.png b/core/res/res/drawable-mdpi/dropdown_disabled_holo_light.9.png
index f54d0b4..1c5cd5e 100644
--- a/core/res/res/drawable-mdpi/dropdown_disabled_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/dropdown_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dropdown_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/dropdown_focused_holo_dark.9.png
index b7044db..06a6518 100644
--- a/core/res/res/drawable-mdpi/dropdown_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/dropdown_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dropdown_focused_holo_light.9.png b/core/res/res/drawable-mdpi/dropdown_focused_holo_light.9.png
index 0de1bb1..0025696 100644
--- a/core/res/res/drawable-mdpi/dropdown_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/dropdown_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dropdown_ic_arrow_disabled_focused_holo_dark.png b/core/res/res/drawable-mdpi/dropdown_ic_arrow_disabled_focused_holo_dark.png
index 95e684a..74c9aa2 100644
--- a/core/res/res/drawable-mdpi/dropdown_ic_arrow_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-mdpi/dropdown_ic_arrow_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dropdown_ic_arrow_disabled_focused_holo_light.png b/core/res/res/drawable-mdpi/dropdown_ic_arrow_disabled_focused_holo_light.png
index ed3e240..aa54a66 100644
--- a/core/res/res/drawable-mdpi/dropdown_ic_arrow_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-mdpi/dropdown_ic_arrow_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dropdown_ic_arrow_disabled_holo_dark.png b/core/res/res/drawable-mdpi/dropdown_ic_arrow_disabled_holo_dark.png
index 2bbfc3a..82f43c7 100644
--- a/core/res/res/drawable-mdpi/dropdown_ic_arrow_disabled_holo_dark.png
+++ b/core/res/res/drawable-mdpi/dropdown_ic_arrow_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dropdown_ic_arrow_disabled_holo_light.png b/core/res/res/drawable-mdpi/dropdown_ic_arrow_disabled_holo_light.png
index db6347b..e8f6903 100644
--- a/core/res/res/drawable-mdpi/dropdown_ic_arrow_disabled_holo_light.png
+++ b/core/res/res/drawable-mdpi/dropdown_ic_arrow_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dropdown_ic_arrow_focused_holo_dark.png b/core/res/res/drawable-mdpi/dropdown_ic_arrow_focused_holo_dark.png
index 9196b72..f2e7dd1 100644
--- a/core/res/res/drawable-mdpi/dropdown_ic_arrow_focused_holo_dark.png
+++ b/core/res/res/drawable-mdpi/dropdown_ic_arrow_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dropdown_ic_arrow_focused_holo_light.png b/core/res/res/drawable-mdpi/dropdown_ic_arrow_focused_holo_light.png
index 7c88a57..490c929 100644
--- a/core/res/res/drawable-mdpi/dropdown_ic_arrow_focused_holo_light.png
+++ b/core/res/res/drawable-mdpi/dropdown_ic_arrow_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dropdown_ic_arrow_normal_holo_dark.png b/core/res/res/drawable-mdpi/dropdown_ic_arrow_normal_holo_dark.png
index 81de1bb..e6f0342 100644
--- a/core/res/res/drawable-mdpi/dropdown_ic_arrow_normal_holo_dark.png
+++ b/core/res/res/drawable-mdpi/dropdown_ic_arrow_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dropdown_ic_arrow_normal_holo_light.png b/core/res/res/drawable-mdpi/dropdown_ic_arrow_normal_holo_light.png
index c3fdef7..e162952 100644
--- a/core/res/res/drawable-mdpi/dropdown_ic_arrow_normal_holo_light.png
+++ b/core/res/res/drawable-mdpi/dropdown_ic_arrow_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dropdown_ic_arrow_pressed_holo_dark.png b/core/res/res/drawable-mdpi/dropdown_ic_arrow_pressed_holo_dark.png
index ef21dc2..bb66de0 100644
--- a/core/res/res/drawable-mdpi/dropdown_ic_arrow_pressed_holo_dark.png
+++ b/core/res/res/drawable-mdpi/dropdown_ic_arrow_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dropdown_ic_arrow_pressed_holo_light.png b/core/res/res/drawable-mdpi/dropdown_ic_arrow_pressed_holo_light.png
index 5352c02..15cce76 100644
--- a/core/res/res/drawable-mdpi/dropdown_ic_arrow_pressed_holo_light.png
+++ b/core/res/res/drawable-mdpi/dropdown_ic_arrow_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dropdown_normal_holo_dark.9.png b/core/res/res/drawable-mdpi/dropdown_normal_holo_dark.9.png
index 05d9e7e..962dbf5 100644
--- a/core/res/res/drawable-mdpi/dropdown_normal_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/dropdown_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dropdown_normal_holo_light.9.png b/core/res/res/drawable-mdpi/dropdown_normal_holo_light.9.png
index 4a15c63..22cca2c 100644
--- a/core/res/res/drawable-mdpi/dropdown_normal_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/dropdown_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dropdown_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/dropdown_pressed_holo_dark.9.png
index 5248c48b..6144566 100644
--- a/core/res/res/drawable-mdpi/dropdown_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/dropdown_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dropdown_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/dropdown_pressed_holo_light.9.png
index f2f6428..19e79a5 100644
--- a/core/res/res/drawable-mdpi/dropdown_pressed_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/dropdown_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/edit_query.png b/core/res/res/drawable-mdpi/edit_query.png
index 22322cb..e9513a6 100644
--- a/core/res/res/drawable-mdpi/edit_query.png
+++ b/core/res/res/drawable-mdpi/edit_query.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/edit_query_background_normal.9.png b/core/res/res/drawable-mdpi/edit_query_background_normal.9.png
index 8f957b8..0376241 100644
--- a/core/res/res/drawable-mdpi/edit_query_background_normal.9.png
+++ b/core/res/res/drawable-mdpi/edit_query_background_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/edit_query_background_pressed.9.png b/core/res/res/drawable-mdpi/edit_query_background_pressed.9.png
index c88d4d5..52ebabb 100644
--- a/core/res/res/drawable-mdpi/edit_query_background_pressed.9.png
+++ b/core/res/res/drawable-mdpi/edit_query_background_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/edit_query_background_selected.9.png b/core/res/res/drawable-mdpi/edit_query_background_selected.9.png
index ffe5791..63b2e64 100644
--- a/core/res/res/drawable-mdpi/edit_query_background_selected.9.png
+++ b/core/res/res/drawable-mdpi/edit_query_background_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/editbox_background_focus_yellow.9.png b/core/res/res/drawable-mdpi/editbox_background_focus_yellow.9.png
index faf52ed..e0ee9f6 100644
--- a/core/res/res/drawable-mdpi/editbox_background_focus_yellow.9.png
+++ b/core/res/res/drawable-mdpi/editbox_background_focus_yellow.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/editbox_background_normal.9.png b/core/res/res/drawable-mdpi/editbox_background_normal.9.png
index 9b8be77..b40f99b 100644
--- a/core/res/res/drawable-mdpi/editbox_background_normal.9.png
+++ b/core/res/res/drawable-mdpi/editbox_background_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/editbox_dropdown_background.9.png b/core/res/res/drawable-mdpi/editbox_dropdown_background.9.png
index ed1bc29..f40df58 100644
--- a/core/res/res/drawable-mdpi/editbox_dropdown_background.9.png
+++ b/core/res/res/drawable-mdpi/editbox_dropdown_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/editbox_dropdown_background_dark.9.png b/core/res/res/drawable-mdpi/editbox_dropdown_background_dark.9.png
index 88c1d9d..a6e22b2 100644
--- a/core/res/res/drawable-mdpi/editbox_dropdown_background_dark.9.png
+++ b/core/res/res/drawable-mdpi/editbox_dropdown_background_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/emo_im_angel.png b/core/res/res/drawable-mdpi/emo_im_angel.png
index 3efea42..5c4013e 100644
--- a/core/res/res/drawable-mdpi/emo_im_angel.png
+++ b/core/res/res/drawable-mdpi/emo_im_angel.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/emo_im_cool.png b/core/res/res/drawable-mdpi/emo_im_cool.png
index 650ed8f..cfb996a 100644
--- a/core/res/res/drawable-mdpi/emo_im_cool.png
+++ b/core/res/res/drawable-mdpi/emo_im_cool.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/emo_im_crying.png b/core/res/res/drawable-mdpi/emo_im_crying.png
index ad1e50f..dab15f9 100644
--- a/core/res/res/drawable-mdpi/emo_im_crying.png
+++ b/core/res/res/drawable-mdpi/emo_im_crying.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/emo_im_embarrassed.png b/core/res/res/drawable-mdpi/emo_im_embarrassed.png
index 8a34321..debcd30 100644
--- a/core/res/res/drawable-mdpi/emo_im_embarrassed.png
+++ b/core/res/res/drawable-mdpi/emo_im_embarrassed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/emo_im_foot_in_mouth.png b/core/res/res/drawable-mdpi/emo_im_foot_in_mouth.png
index 9607ff7..e59f8e2 100644
--- a/core/res/res/drawable-mdpi/emo_im_foot_in_mouth.png
+++ b/core/res/res/drawable-mdpi/emo_im_foot_in_mouth.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/emo_im_happy.png b/core/res/res/drawable-mdpi/emo_im_happy.png
index a324720..f210b23 100644
--- a/core/res/res/drawable-mdpi/emo_im_happy.png
+++ b/core/res/res/drawable-mdpi/emo_im_happy.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/emo_im_kissing.png b/core/res/res/drawable-mdpi/emo_im_kissing.png
index f18a391..0e118bf 100644
--- a/core/res/res/drawable-mdpi/emo_im_kissing.png
+++ b/core/res/res/drawable-mdpi/emo_im_kissing.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/emo_im_laughing.png b/core/res/res/drawable-mdpi/emo_im_laughing.png
index 963a4ba..21728ca 100644
--- a/core/res/res/drawable-mdpi/emo_im_laughing.png
+++ b/core/res/res/drawable-mdpi/emo_im_laughing.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/emo_im_lips_are_sealed.png b/core/res/res/drawable-mdpi/emo_im_lips_are_sealed.png
index 58bd138..c5ff54f 100644
--- a/core/res/res/drawable-mdpi/emo_im_lips_are_sealed.png
+++ b/core/res/res/drawable-mdpi/emo_im_lips_are_sealed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/emo_im_money_mouth.png b/core/res/res/drawable-mdpi/emo_im_money_mouth.png
index 718c7e3..3072b93 100644
--- a/core/res/res/drawable-mdpi/emo_im_money_mouth.png
+++ b/core/res/res/drawable-mdpi/emo_im_money_mouth.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/emo_im_sad.png b/core/res/res/drawable-mdpi/emo_im_sad.png
index 7daac6c..8b95026 100644
--- a/core/res/res/drawable-mdpi/emo_im_sad.png
+++ b/core/res/res/drawable-mdpi/emo_im_sad.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/emo_im_surprised.png b/core/res/res/drawable-mdpi/emo_im_surprised.png
index b4b614d..bdd35d6 100644
--- a/core/res/res/drawable-mdpi/emo_im_surprised.png
+++ b/core/res/res/drawable-mdpi/emo_im_surprised.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/emo_im_tongue_sticking_out.png b/core/res/res/drawable-mdpi/emo_im_tongue_sticking_out.png
index 9fa6534..bff7e19 100644
--- a/core/res/res/drawable-mdpi/emo_im_tongue_sticking_out.png
+++ b/core/res/res/drawable-mdpi/emo_im_tongue_sticking_out.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/emo_im_undecided.png b/core/res/res/drawable-mdpi/emo_im_undecided.png
index 8b2577a..aa22e97 100644
--- a/core/res/res/drawable-mdpi/emo_im_undecided.png
+++ b/core/res/res/drawable-mdpi/emo_im_undecided.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/emo_im_winking.png b/core/res/res/drawable-mdpi/emo_im_winking.png
index 069e9e3..aaf574c 100644
--- a/core/res/res/drawable-mdpi/emo_im_winking.png
+++ b/core/res/res/drawable-mdpi/emo_im_winking.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/emo_im_wtf.png b/core/res/res/drawable-mdpi/emo_im_wtf.png
index 0d963ec..2487023 100644
--- a/core/res/res/drawable-mdpi/emo_im_wtf.png
+++ b/core/res/res/drawable-mdpi/emo_im_wtf.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/emo_im_yelling.png b/core/res/res/drawable-mdpi/emo_im_yelling.png
index 836f60f..ee9400b 100644
--- a/core/res/res/drawable-mdpi/emo_im_yelling.png
+++ b/core/res/res/drawable-mdpi/emo_im_yelling.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/expander_close_holo_dark.9.png b/core/res/res/drawable-mdpi/expander_close_holo_dark.9.png
index 036ffb7..095b23b 100644
--- a/core/res/res/drawable-mdpi/expander_close_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/expander_close_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/expander_close_holo_light.9.png b/core/res/res/drawable-mdpi/expander_close_holo_light.9.png
index 9f9dd70..62fdd4c 100644
--- a/core/res/res/drawable-mdpi/expander_close_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/expander_close_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/expander_close_mtrl_alpha.9.png b/core/res/res/drawable-mdpi/expander_close_mtrl_alpha.9.png
index 6070397..612d0ef 100644
--- a/core/res/res/drawable-mdpi/expander_close_mtrl_alpha.9.png
+++ b/core/res/res/drawable-mdpi/expander_close_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/expander_ic_maximized.9.png b/core/res/res/drawable-mdpi/expander_ic_maximized.9.png
index d5c3276..10e8bf8 100644
--- a/core/res/res/drawable-mdpi/expander_ic_maximized.9.png
+++ b/core/res/res/drawable-mdpi/expander_ic_maximized.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/expander_ic_minimized.9.png b/core/res/res/drawable-mdpi/expander_ic_minimized.9.png
index 4515b42..0b0eac1 100644
--- a/core/res/res/drawable-mdpi/expander_ic_minimized.9.png
+++ b/core/res/res/drawable-mdpi/expander_ic_minimized.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/expander_open_holo_dark.9.png b/core/res/res/drawable-mdpi/expander_open_holo_dark.9.png
index 867f36d..222a9f0 100644
--- a/core/res/res/drawable-mdpi/expander_open_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/expander_open_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/expander_open_holo_light.9.png b/core/res/res/drawable-mdpi/expander_open_holo_light.9.png
index 7f5ca48..f148fbc 100644
--- a/core/res/res/drawable-mdpi/expander_open_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/expander_open_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/expander_open_mtrl_alpha.9.png b/core/res/res/drawable-mdpi/expander_open_mtrl_alpha.9.png
index 29a3a1a..8a5c6b6 100644
--- a/core/res/res/drawable-mdpi/expander_open_mtrl_alpha.9.png
+++ b/core/res/res/drawable-mdpi/expander_open_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/fastscroll_label_left_holo_dark.9.png b/core/res/res/drawable-mdpi/fastscroll_label_left_holo_dark.9.png
index 94b944d..5a89976 100644
--- a/core/res/res/drawable-mdpi/fastscroll_label_left_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/fastscroll_label_left_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/fastscroll_label_left_holo_light.9.png b/core/res/res/drawable-mdpi/fastscroll_label_left_holo_light.9.png
index 987c097..3149f4e 100644
--- a/core/res/res/drawable-mdpi/fastscroll_label_left_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/fastscroll_label_left_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/fastscroll_label_right_holo_dark.9.png b/core/res/res/drawable-mdpi/fastscroll_label_right_holo_dark.9.png
index 8d87032..e54b7db 100644
--- a/core/res/res/drawable-mdpi/fastscroll_label_right_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/fastscroll_label_right_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/fastscroll_label_right_holo_light.9.png b/core/res/res/drawable-mdpi/fastscroll_label_right_holo_light.9.png
index b29042a..e0178f3 100644
--- a/core/res/res/drawable-mdpi/fastscroll_label_right_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/fastscroll_label_right_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/fastscroll_thumb_default_holo.png b/core/res/res/drawable-mdpi/fastscroll_thumb_default_holo.png
index 9dddbd2..86f87be 100644
--- a/core/res/res/drawable-mdpi/fastscroll_thumb_default_holo.png
+++ b/core/res/res/drawable-mdpi/fastscroll_thumb_default_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/fastscroll_thumb_pressed_holo.png b/core/res/res/drawable-mdpi/fastscroll_thumb_pressed_holo.png
index 6da2c1c..1202b78 100644
--- a/core/res/res/drawable-mdpi/fastscroll_thumb_pressed_holo.png
+++ b/core/res/res/drawable-mdpi/fastscroll_thumb_pressed_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/fastscroll_track_default_holo_dark.9.png b/core/res/res/drawable-mdpi/fastscroll_track_default_holo_dark.9.png
index eb2b8bd..d08fded 100644
--- a/core/res/res/drawable-mdpi/fastscroll_track_default_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/fastscroll_track_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/fastscroll_track_default_holo_light.9.png b/core/res/res/drawable-mdpi/fastscroll_track_default_holo_light.9.png
index eb2b8bd..d08fded 100644
--- a/core/res/res/drawable-mdpi/fastscroll_track_default_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/fastscroll_track_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/fastscroll_track_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/fastscroll_track_pressed_holo_dark.9.png
index 6fb59b6..c7e7b82 100644
--- a/core/res/res/drawable-mdpi/fastscroll_track_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/fastscroll_track_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/fastscroll_track_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/fastscroll_track_pressed_holo_light.9.png
index 1a63f5d..9b9b06b 100644
--- a/core/res/res/drawable-mdpi/fastscroll_track_pressed_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/fastscroll_track_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/focused_application_background_static.png b/core/res/res/drawable-mdpi/focused_application_background_static.png
index fd18d30..b1d03f0 100644
--- a/core/res/res/drawable-mdpi/focused_application_background_static.png
+++ b/core/res/res/drawable-mdpi/focused_application_background_static.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/frame_gallery_thumb.9.png b/core/res/res/drawable-mdpi/frame_gallery_thumb.9.png
index 804f6f3..4b5aff4 100644
--- a/core/res/res/drawable-mdpi/frame_gallery_thumb.9.png
+++ b/core/res/res/drawable-mdpi/frame_gallery_thumb.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/frame_gallery_thumb_pressed.9.png b/core/res/res/drawable-mdpi/frame_gallery_thumb_pressed.9.png
index e1ffa06..89675ea 100644
--- a/core/res/res/drawable-mdpi/frame_gallery_thumb_pressed.9.png
+++ b/core/res/res/drawable-mdpi/frame_gallery_thumb_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/frame_gallery_thumb_selected.9.png b/core/res/res/drawable-mdpi/frame_gallery_thumb_selected.9.png
index 8bae932..11554e4 100644
--- a/core/res/res/drawable-mdpi/frame_gallery_thumb_selected.9.png
+++ b/core/res/res/drawable-mdpi/frame_gallery_thumb_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/gallery_selected_default.9.png b/core/res/res/drawable-mdpi/gallery_selected_default.9.png
index 22122b2..34e9e63 100644
--- a/core/res/res/drawable-mdpi/gallery_selected_default.9.png
+++ b/core/res/res/drawable-mdpi/gallery_selected_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/gallery_selected_focused.9.png b/core/res/res/drawable-mdpi/gallery_selected_focused.9.png
index 1332745..9f3b3ea 100644
--- a/core/res/res/drawable-mdpi/gallery_selected_focused.9.png
+++ b/core/res/res/drawable-mdpi/gallery_selected_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/gallery_selected_pressed.9.png b/core/res/res/drawable-mdpi/gallery_selected_pressed.9.png
index 306e543..50f4096 100644
--- a/core/res/res/drawable-mdpi/gallery_selected_pressed.9.png
+++ b/core/res/res/drawable-mdpi/gallery_selected_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/gallery_unselected_default.9.png b/core/res/res/drawable-mdpi/gallery_unselected_default.9.png
index 0df06fa..a17538e 100644
--- a/core/res/res/drawable-mdpi/gallery_unselected_default.9.png
+++ b/core/res/res/drawable-mdpi/gallery_unselected_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/gallery_unselected_pressed.9.png b/core/res/res/drawable-mdpi/gallery_unselected_pressed.9.png
index 4b25c3f..822c6c8 100644
--- a/core/res/res/drawable-mdpi/gallery_unselected_pressed.9.png
+++ b/core/res/res/drawable-mdpi/gallery_unselected_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/grid_selector_background_focus.9.png b/core/res/res/drawable-mdpi/grid_selector_background_focus.9.png
index 2e28232..95ba1c8 100644
--- a/core/res/res/drawable-mdpi/grid_selector_background_focus.9.png
+++ b/core/res/res/drawable-mdpi/grid_selector_background_focus.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/grid_selector_background_pressed.9.png b/core/res/res/drawable-mdpi/grid_selector_background_pressed.9.png
index e20f091..a4ee2d4 100644
--- a/core/res/res/drawable-mdpi/grid_selector_background_pressed.9.png
+++ b/core/res/res/drawable-mdpi/grid_selector_background_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/highlight_disabled.9.png b/core/res/res/drawable-mdpi/highlight_disabled.9.png
index 1393262..8145645 100644
--- a/core/res/res/drawable-mdpi/highlight_disabled.9.png
+++ b/core/res/res/drawable-mdpi/highlight_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/highlight_pressed.9.png b/core/res/res/drawable-mdpi/highlight_pressed.9.png
index 9bd2b50..02eff0b2 100644
--- a/core/res/res/drawable-mdpi/highlight_pressed.9.png
+++ b/core/res/res/drawable-mdpi/highlight_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/highlight_selected.9.png b/core/res/res/drawable-mdpi/highlight_selected.9.png
index ecf0cad..3ade2b4 100644
--- a/core/res/res/drawable-mdpi/highlight_selected.9.png
+++ b/core/res/res/drawable-mdpi/highlight_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_ab_back_holo_dark_am.png b/core/res/res/drawable-mdpi/ic_ab_back_holo_dark_am.png
index df2d3d1..87c5b8b 100644
--- a/core/res/res/drawable-mdpi/ic_ab_back_holo_dark_am.png
+++ b/core/res/res/drawable-mdpi/ic_ab_back_holo_dark_am.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_ab_back_holo_light_am.png b/core/res/res/drawable-mdpi/ic_ab_back_holo_light_am.png
index b2aa9c2..ccc2d18 100644
--- a/core/res/res/drawable-mdpi/ic_ab_back_holo_light_am.png
+++ b/core/res/res/drawable-mdpi/ic_ab_back_holo_light_am.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_action_assist_focused.png b/core/res/res/drawable-mdpi/ic_action_assist_focused.png
index 3f96d03..4349a9c 100644
--- a/core/res/res/drawable-mdpi/ic_action_assist_focused.png
+++ b/core/res/res/drawable-mdpi/ic_action_assist_focused.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_aggregated.png b/core/res/res/drawable-mdpi/ic_aggregated.png
index ad42071..0ec37b0 100644
--- a/core/res/res/drawable-mdpi/ic_aggregated.png
+++ b/core/res/res/drawable-mdpi/ic_aggregated.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_notification_am_alpha.png b/core/res/res/drawable-mdpi/ic_audio_notification_am_alpha.png
index b41ccd0..b16fe69 100644
--- a/core/res/res/drawable-mdpi/ic_audio_notification_am_alpha.png
+++ b/core/res/res/drawable-mdpi/ic_audio_notification_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_notification_mute_am_alpha.png b/core/res/res/drawable-mdpi/ic_audio_notification_mute_am_alpha.png
index 2567f76..0bb0879 100644
--- a/core/res/res/drawable-mdpi/ic_audio_notification_mute_am_alpha.png
+++ b/core/res/res/drawable-mdpi/ic_audio_notification_mute_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_btn_round_more_disabled.png b/core/res/res/drawable-mdpi/ic_btn_round_more_disabled.png
index 428edf2..d8d9d0d 100644
--- a/core/res/res/drawable-mdpi/ic_btn_round_more_disabled.png
+++ b/core/res/res/drawable-mdpi/ic_btn_round_more_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_btn_round_more_normal.png b/core/res/res/drawable-mdpi/ic_btn_round_more_normal.png
index c2ecb01..d624fb1 100644
--- a/core/res/res/drawable-mdpi/ic_btn_round_more_normal.png
+++ b/core/res/res/drawable-mdpi/ic_btn_round_more_normal.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_btn_search_go.png b/core/res/res/drawable-mdpi/ic_btn_search_go.png
index 9a4e9b9..9bed1a1 100644
--- a/core/res/res/drawable-mdpi/ic_btn_search_go.png
+++ b/core/res/res/drawable-mdpi/ic_btn_search_go.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_btn_speak_now.png b/core/res/res/drawable-mdpi/ic_btn_speak_now.png
index 0589be6..157dc0f 100644
--- a/core/res/res/drawable-mdpi/ic_btn_speak_now.png
+++ b/core/res/res/drawable-mdpi/ic_btn_speak_now.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_btn_square_browser_zoom_fit_page_disabled.png b/core/res/res/drawable-mdpi/ic_btn_square_browser_zoom_fit_page_disabled.png
index 914662d..5d036c8 100644
--- a/core/res/res/drawable-mdpi/ic_btn_square_browser_zoom_fit_page_disabled.png
+++ b/core/res/res/drawable-mdpi/ic_btn_square_browser_zoom_fit_page_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_btn_square_browser_zoom_fit_page_normal.png b/core/res/res/drawable-mdpi/ic_btn_square_browser_zoom_fit_page_normal.png
index 3b67c6d..ed9e5bf 100644
--- a/core/res/res/drawable-mdpi/ic_btn_square_browser_zoom_fit_page_normal.png
+++ b/core/res/res/drawable-mdpi/ic_btn_square_browser_zoom_fit_page_normal.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_btn_square_browser_zoom_page_overview_disabled.png b/core/res/res/drawable-mdpi/ic_btn_square_browser_zoom_page_overview_disabled.png
index 859900a..3335705 100644
--- a/core/res/res/drawable-mdpi/ic_btn_square_browser_zoom_page_overview_disabled.png
+++ b/core/res/res/drawable-mdpi/ic_btn_square_browser_zoom_page_overview_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_btn_square_browser_zoom_page_overview_normal.png b/core/res/res/drawable-mdpi/ic_btn_square_browser_zoom_page_overview_normal.png
index 4e8ff35..446c6c0 100644
--- a/core/res/res/drawable-mdpi/ic_btn_square_browser_zoom_page_overview_normal.png
+++ b/core/res/res/drawable-mdpi/ic_btn_square_browser_zoom_page_overview_normal.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_bullet_key_permission.png b/core/res/res/drawable-mdpi/ic_bullet_key_permission.png
index 7fee560..65ecd35 100644
--- a/core/res/res/drawable-mdpi/ic_bullet_key_permission.png
+++ b/core/res/res/drawable-mdpi/ic_bullet_key_permission.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_cab_done_holo.png b/core/res/res/drawable-mdpi/ic_cab_done_holo.png
index f5c27a6..962827b 100644
--- a/core/res/res/drawable-mdpi/ic_cab_done_holo.png
+++ b/core/res/res/drawable-mdpi/ic_cab_done_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_cab_done_holo_dark.png b/core/res/res/drawable-mdpi/ic_cab_done_holo_dark.png
index a17b6a7..3ac3267 100644
--- a/core/res/res/drawable-mdpi/ic_cab_done_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_cab_done_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_cab_done_holo_light.png b/core/res/res/drawable-mdpi/ic_cab_done_holo_light.png
index b28b3b5..a4bad31 100644
--- a/core/res/res/drawable-mdpi/ic_cab_done_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_cab_done_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_cab_done_mtrl_alpha.png b/core/res/res/drawable-mdpi/ic_cab_done_mtrl_alpha.png
index 541184a..9c1bf68 100644
--- a/core/res/res/drawable-mdpi/ic_cab_done_mtrl_alpha.png
+++ b/core/res/res/drawable-mdpi/ic_cab_done_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_checkmark_holo_light.png b/core/res/res/drawable-mdpi/ic_checkmark_holo_light.png
index 744e964..87baf84 100644
--- a/core/res/res/drawable-mdpi/ic_checkmark_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_checkmark_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_clear_disabled.png b/core/res/res/drawable-mdpi/ic_clear_disabled.png
index 79228ba..e0908de 100644
--- a/core/res/res/drawable-mdpi/ic_clear_disabled.png
+++ b/core/res/res/drawable-mdpi/ic_clear_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_clear_normal.png b/core/res/res/drawable-mdpi/ic_clear_normal.png
index 86944a8..172916b 100644
--- a/core/res/res/drawable-mdpi/ic_clear_normal.png
+++ b/core/res/res/drawable-mdpi/ic_clear_normal.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_clear_search_api_disabled_holo_dark.png b/core/res/res/drawable-mdpi/ic_clear_search_api_disabled_holo_dark.png
index 6a34dba..6f994ae 100644
--- a/core/res/res/drawable-mdpi/ic_clear_search_api_disabled_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_clear_search_api_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_clear_search_api_disabled_holo_light.png b/core/res/res/drawable-mdpi/ic_clear_search_api_disabled_holo_light.png
index c0bdf06..d354a76 100644
--- a/core/res/res/drawable-mdpi/ic_clear_search_api_disabled_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_clear_search_api_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_clear_search_api_holo_dark.png b/core/res/res/drawable-mdpi/ic_clear_search_api_holo_dark.png
index ee16528..0694799 100644
--- a/core/res/res/drawable-mdpi/ic_clear_search_api_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_clear_search_api_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_clear_search_api_holo_light.png b/core/res/res/drawable-mdpi/ic_clear_search_api_holo_light.png
index 15b86cb..54ffb8e 100644
--- a/core/res/res/drawable-mdpi/ic_clear_search_api_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_clear_search_api_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_coins_l.png b/core/res/res/drawable-mdpi/ic_coins_l.png
index a6d7abb..f7a7f5c 100644
--- a/core/res/res/drawable-mdpi/ic_coins_l.png
+++ b/core/res/res/drawable-mdpi/ic_coins_l.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_coins_s.png b/core/res/res/drawable-mdpi/ic_coins_s.png
index 3b8fd8a..7ee214c 100644
--- a/core/res/res/drawable-mdpi/ic_coins_s.png
+++ b/core/res/res/drawable-mdpi/ic_coins_s.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_commit.png b/core/res/res/drawable-mdpi/ic_commit.png
index 3d167b5..5cd25de 100644
--- a/core/res/res/drawable-mdpi/ic_commit.png
+++ b/core/res/res/drawable-mdpi/ic_commit.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_commit_search_api_holo_dark.png b/core/res/res/drawable-mdpi/ic_commit_search_api_holo_dark.png
index 844c99c..45e6d1a 100644
--- a/core/res/res/drawable-mdpi/ic_commit_search_api_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_commit_search_api_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_commit_search_api_holo_light.png b/core/res/res/drawable-mdpi/ic_commit_search_api_holo_light.png
index 86c170e..b56c965 100644
--- a/core/res/res/drawable-mdpi/ic_commit_search_api_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_commit_search_api_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_commit_search_api_mtrl_alpha.png b/core/res/res/drawable-mdpi/ic_commit_search_api_mtrl_alpha.png
index 42ac8ca..922b4d5 100644
--- a/core/res/res/drawable-mdpi/ic_commit_search_api_mtrl_alpha.png
+++ b/core/res/res/drawable-mdpi/ic_commit_search_api_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_contact_picture.png b/core/res/res/drawable-mdpi/ic_contact_picture.png
index 771cb6b..c035498 100644
--- a/core/res/res/drawable-mdpi/ic_contact_picture.png
+++ b/core/res/res/drawable-mdpi/ic_contact_picture.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_contact_picture_2.png b/core/res/res/drawable-mdpi/ic_contact_picture_2.png
index 004a6c6..a4457f5 100644
--- a/core/res/res/drawable-mdpi/ic_contact_picture_2.png
+++ b/core/res/res/drawable-mdpi/ic_contact_picture_2.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_contact_picture_3.png b/core/res/res/drawable-mdpi/ic_contact_picture_3.png
index 001bf29..7f29f9e 100644
--- a/core/res/res/drawable-mdpi/ic_contact_picture_3.png
+++ b/core/res/res/drawable-mdpi/ic_contact_picture_3.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_delete.png b/core/res/res/drawable-mdpi/ic_delete.png
index f074db3..1d688f8 100644
--- a/core/res/res/drawable-mdpi/ic_delete.png
+++ b/core/res/res/drawable-mdpi/ic_delete.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_dialog_alert.png b/core/res/res/drawable-mdpi/ic_dialog_alert.png
index ef498ef..eca1476 100644
--- a/core/res/res/drawable-mdpi/ic_dialog_alert.png
+++ b/core/res/res/drawable-mdpi/ic_dialog_alert.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_dialog_alert_holo_dark.png b/core/res/res/drawable-mdpi/ic_dialog_alert_holo_dark.png
index 75d9db7..9ad33d2 100644
--- a/core/res/res/drawable-mdpi/ic_dialog_alert_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_dialog_alert_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_dialog_alert_holo_light.png b/core/res/res/drawable-mdpi/ic_dialog_alert_holo_light.png
index 9e7f0bd..59fbf05 100644
--- a/core/res/res/drawable-mdpi/ic_dialog_alert_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_dialog_alert_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_dialog_close_normal_holo.png b/core/res/res/drawable-mdpi/ic_dialog_close_normal_holo.png
index 7f2a029..8537241 100644
--- a/core/res/res/drawable-mdpi/ic_dialog_close_normal_holo.png
+++ b/core/res/res/drawable-mdpi/ic_dialog_close_normal_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_dialog_close_pressed_holo.png b/core/res/res/drawable-mdpi/ic_dialog_close_pressed_holo.png
index daa8e18..601656e 100644
--- a/core/res/res/drawable-mdpi/ic_dialog_close_pressed_holo.png
+++ b/core/res/res/drawable-mdpi/ic_dialog_close_pressed_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_dialog_dialer.png b/core/res/res/drawable-mdpi/ic_dialog_dialer.png
index f0c1838..aaddc58 100644
--- a/core/res/res/drawable-mdpi/ic_dialog_dialer.png
+++ b/core/res/res/drawable-mdpi/ic_dialog_dialer.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_dialog_email.png b/core/res/res/drawable-mdpi/ic_dialog_email.png
index 20ebb13..562f8f40 100644
--- a/core/res/res/drawable-mdpi/ic_dialog_email.png
+++ b/core/res/res/drawable-mdpi/ic_dialog_email.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_dialog_focused_holo.png b/core/res/res/drawable-mdpi/ic_dialog_focused_holo.png
index 179f2de..0a7950d 100644
--- a/core/res/res/drawable-mdpi/ic_dialog_focused_holo.png
+++ b/core/res/res/drawable-mdpi/ic_dialog_focused_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_dialog_info.png b/core/res/res/drawable-mdpi/ic_dialog_info.png
index e8b0229..d0f198b 100644
--- a/core/res/res/drawable-mdpi/ic_dialog_info.png
+++ b/core/res/res/drawable-mdpi/ic_dialog_info.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_dialog_map.png b/core/res/res/drawable-mdpi/ic_dialog_map.png
index b126354..d24cb2b 100644
--- a/core/res/res/drawable-mdpi/ic_dialog_map.png
+++ b/core/res/res/drawable-mdpi/ic_dialog_map.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_dialog_time.png b/core/res/res/drawable-mdpi/ic_dialog_time.png
index dffec29..f258ef7 100644
--- a/core/res/res/drawable-mdpi/ic_dialog_time.png
+++ b/core/res/res/drawable-mdpi/ic_dialog_time.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_dialog_usb.png b/core/res/res/drawable-mdpi/ic_dialog_usb.png
index fbc8a9d..b1d1241 100644
--- a/core/res/res/drawable-mdpi/ic_dialog_usb.png
+++ b/core/res/res/drawable-mdpi/ic_dialog_usb.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_emergency.png b/core/res/res/drawable-mdpi/ic_emergency.png
index dfa17c6..fe56c14 100644
--- a/core/res/res/drawable-mdpi/ic_emergency.png
+++ b/core/res/res/drawable-mdpi/ic_emergency.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_find_next_holo_dark.png b/core/res/res/drawable-mdpi/ic_find_next_holo_dark.png
index c138916..cf90575 100644
--- a/core/res/res/drawable-mdpi/ic_find_next_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_find_next_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_find_next_holo_light.png b/core/res/res/drawable-mdpi/ic_find_next_holo_light.png
index 4eea3c3..36a745a 100644
--- a/core/res/res/drawable-mdpi/ic_find_next_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_find_next_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_find_next_mtrl_alpha.png b/core/res/res/drawable-mdpi/ic_find_next_mtrl_alpha.png
index 1cfdb3f..9125fc7 100644
--- a/core/res/res/drawable-mdpi/ic_find_next_mtrl_alpha.png
+++ b/core/res/res/drawable-mdpi/ic_find_next_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_find_previous_holo_dark.png b/core/res/res/drawable-mdpi/ic_find_previous_holo_dark.png
index d239274..d4bed40 100644
--- a/core/res/res/drawable-mdpi/ic_find_previous_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_find_previous_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_find_previous_holo_light.png b/core/res/res/drawable-mdpi/ic_find_previous_holo_light.png
index 786e1d6..b39ba77 100644
--- a/core/res/res/drawable-mdpi/ic_find_previous_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_find_previous_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_find_previous_mtrl_alpha.png b/core/res/res/drawable-mdpi/ic_find_previous_mtrl_alpha.png
index 0d3c009..9902cf2 100644
--- a/core/res/res/drawable-mdpi/ic_find_previous_mtrl_alpha.png
+++ b/core/res/res/drawable-mdpi/ic_find_previous_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_go.png b/core/res/res/drawable-mdpi/ic_go.png
index bf19833..590b82a 100644
--- a/core/res/res/drawable-mdpi/ic_go.png
+++ b/core/res/res/drawable-mdpi/ic_go.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_go_search_api_holo_dark.png b/core/res/res/drawable-mdpi/ic_go_search_api_holo_dark.png
index 591f734..7980cb5 100644
--- a/core/res/res/drawable-mdpi/ic_go_search_api_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_go_search_api_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_go_search_api_holo_light.png b/core/res/res/drawable-mdpi/ic_go_search_api_holo_light.png
index 8518498..959eaaf 100644
--- a/core/res/res/drawable-mdpi/ic_go_search_api_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_go_search_api_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_input_add.png b/core/res/res/drawable-mdpi/ic_input_add.png
index 00770f8..d7801a6 100644
--- a/core/res/res/drawable-mdpi/ic_input_add.png
+++ b/core/res/res/drawable-mdpi/ic_input_add.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_input_delete.png b/core/res/res/drawable-mdpi/ic_input_delete.png
index 47c8708..3d7611d 100644
--- a/core/res/res/drawable-mdpi/ic_input_delete.png
+++ b/core/res/res/drawable-mdpi/ic_input_delete.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_input_get.png b/core/res/res/drawable-mdpi/ic_input_get.png
index 2f2cfcf..8126f3b 100644
--- a/core/res/res/drawable-mdpi/ic_input_get.png
+++ b/core/res/res/drawable-mdpi/ic_input_get.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_jog_dial_answer.png b/core/res/res/drawable-mdpi/ic_jog_dial_answer.png
index e2bc483..673afa7 100644
--- a/core/res/res/drawable-mdpi/ic_jog_dial_answer.png
+++ b/core/res/res/drawable-mdpi/ic_jog_dial_answer.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_jog_dial_answer_and_end.png b/core/res/res/drawable-mdpi/ic_jog_dial_answer_and_end.png
index aa0fab2..bc7b4e9 100644
--- a/core/res/res/drawable-mdpi/ic_jog_dial_answer_and_end.png
+++ b/core/res/res/drawable-mdpi/ic_jog_dial_answer_and_end.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_jog_dial_answer_and_hold.png b/core/res/res/drawable-mdpi/ic_jog_dial_answer_and_hold.png
index 9effe37..cd76382 100644
--- a/core/res/res/drawable-mdpi/ic_jog_dial_answer_and_hold.png
+++ b/core/res/res/drawable-mdpi/ic_jog_dial_answer_and_hold.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_jog_dial_decline.png b/core/res/res/drawable-mdpi/ic_jog_dial_decline.png
index 81c76b5..d189a10 100644
--- a/core/res/res/drawable-mdpi/ic_jog_dial_decline.png
+++ b/core/res/res/drawable-mdpi/ic_jog_dial_decline.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_jog_dial_sound_off.png b/core/res/res/drawable-mdpi/ic_jog_dial_sound_off.png
index b9aec69..cabb5a6 100644
--- a/core/res/res/drawable-mdpi/ic_jog_dial_sound_off.png
+++ b/core/res/res/drawable-mdpi/ic_jog_dial_sound_off.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_jog_dial_sound_on.png b/core/res/res/drawable-mdpi/ic_jog_dial_sound_on.png
index 4952746..7b9b265 100644
--- a/core/res/res/drawable-mdpi/ic_jog_dial_sound_on.png
+++ b/core/res/res/drawable-mdpi/ic_jog_dial_sound_on.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_jog_dial_unlock.png b/core/res/res/drawable-mdpi/ic_jog_dial_unlock.png
index e697d91..17ae139 100644
--- a/core/res/res/drawable-mdpi/ic_jog_dial_unlock.png
+++ b/core/res/res/drawable-mdpi/ic_jog_dial_unlock.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_jog_dial_vibrate_on.png b/core/res/res/drawable-mdpi/ic_jog_dial_vibrate_on.png
index 9aa9b13..d6649dd 100644
--- a/core/res/res/drawable-mdpi/ic_jog_dial_vibrate_on.png
+++ b/core/res/res/drawable-mdpi/ic_jog_dial_vibrate_on.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_launcher_android.png b/core/res/res/drawable-mdpi/ic_launcher_android.png
index 16b66a1..fd3b2dd 100644
--- a/core/res/res/drawable-mdpi/ic_launcher_android.png
+++ b/core/res/res/drawable-mdpi/ic_launcher_android.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_airplane_mode_alpha.png b/core/res/res/drawable-mdpi/ic_lock_airplane_mode_alpha.png
index 2b1dc1a..2a09e5b 100644
--- a/core/res/res/drawable-mdpi/ic_lock_airplane_mode_alpha.png
+++ b/core/res/res/drawable-mdpi/ic_lock_airplane_mode_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_airplane_mode_off_am_alpha.png b/core/res/res/drawable-mdpi/ic_lock_airplane_mode_off_am_alpha.png
index 49ed3d2..108ed99 100644
--- a/core/res/res/drawable-mdpi/ic_lock_airplane_mode_off_am_alpha.png
+++ b/core/res/res/drawable-mdpi/ic_lock_airplane_mode_off_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_idle_alarm_alpha.png b/core/res/res/drawable-mdpi/ic_lock_idle_alarm_alpha.png
index b5d3e09..ccfcd1c 100644
--- a/core/res/res/drawable-mdpi/ic_lock_idle_alarm_alpha.png
+++ b/core/res/res/drawable-mdpi/ic_lock_idle_alarm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_idle_charging.png b/core/res/res/drawable-mdpi/ic_lock_idle_charging.png
index 20d6320..e3cc0c9 100644
--- a/core/res/res/drawable-mdpi/ic_lock_idle_charging.png
+++ b/core/res/res/drawable-mdpi/ic_lock_idle_charging.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_idle_lock.png b/core/res/res/drawable-mdpi/ic_lock_idle_lock.png
index 0206aee..9de906e 100644
--- a/core/res/res/drawable-mdpi/ic_lock_idle_lock.png
+++ b/core/res/res/drawable-mdpi/ic_lock_idle_lock.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_idle_low_battery.png b/core/res/res/drawable-mdpi/ic_lock_idle_low_battery.png
index bb96782..f646028b8 100644
--- a/core/res/res/drawable-mdpi/ic_lock_idle_low_battery.png
+++ b/core/res/res/drawable-mdpi/ic_lock_idle_low_battery.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_lock_alpha.png b/core/res/res/drawable-mdpi/ic_lock_lock_alpha.png
index 5ff3654..48e26cb 100644
--- a/core/res/res/drawable-mdpi/ic_lock_lock_alpha.png
+++ b/core/res/res/drawable-mdpi/ic_lock_lock_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_open_wht_24dp.png b/core/res/res/drawable-mdpi/ic_lock_open_wht_24dp.png
index 163f4a0..b863904 100644
--- a/core/res/res/drawable-mdpi/ic_lock_open_wht_24dp.png
+++ b/core/res/res/drawable-mdpi/ic_lock_open_wht_24dp.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_outline_wht_24dp.png b/core/res/res/drawable-mdpi/ic_lock_outline_wht_24dp.png
index bbfb83c7..20b5e7b 100644
--- a/core/res/res/drawable-mdpi/ic_lock_outline_wht_24dp.png
+++ b/core/res/res/drawable-mdpi/ic_lock_outline_wht_24dp.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_power_off_alpha.png b/core/res/res/drawable-mdpi/ic_lock_power_off_alpha.png
index 2c55e47..9fe297a 100644
--- a/core/res/res/drawable-mdpi/ic_lock_power_off_alpha.png
+++ b/core/res/res/drawable-mdpi/ic_lock_power_off_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_ringer_off_alpha.png b/core/res/res/drawable-mdpi/ic_lock_ringer_off_alpha.png
index 98cfb11..06fc5a3 100644
--- a/core/res/res/drawable-mdpi/ic_lock_ringer_off_alpha.png
+++ b/core/res/res/drawable-mdpi/ic_lock_ringer_off_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_ringer_on_alpha.png b/core/res/res/drawable-mdpi/ic_lock_ringer_on_alpha.png
index 691b99e..534b724 100644
--- a/core/res/res/drawable-mdpi/ic_lock_ringer_on_alpha.png
+++ b/core/res/res/drawable-mdpi/ic_lock_ringer_on_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_silent_mode.png b/core/res/res/drawable-mdpi/ic_lock_silent_mode.png
index 5c3a226..683bb53 100644
--- a/core/res/res/drawable-mdpi/ic_lock_silent_mode.png
+++ b/core/res/res/drawable-mdpi/ic_lock_silent_mode.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_silent_mode_off.png b/core/res/res/drawable-mdpi/ic_lock_silent_mode_off.png
index 1a02aaa..fcf5475 100644
--- a/core/res/res/drawable-mdpi/ic_lock_silent_mode_off.png
+++ b/core/res/res/drawable-mdpi/ic_lock_silent_mode_off.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_silent_mode_vibrate.png b/core/res/res/drawable-mdpi/ic_lock_silent_mode_vibrate.png
index 7da79aa..4376954 100644
--- a/core/res/res/drawable-mdpi/ic_lock_silent_mode_vibrate.png
+++ b/core/res/res/drawable-mdpi/ic_lock_silent_mode_vibrate.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_handle_pressed.png b/core/res/res/drawable-mdpi/ic_lockscreen_handle_pressed.png
index 0187a02..eff82cd 100644
--- a/core/res/res/drawable-mdpi/ic_lockscreen_handle_pressed.png
+++ b/core/res/res/drawable-mdpi/ic_lockscreen_handle_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_maps_indicator_current_position.png b/core/res/res/drawable-mdpi/ic_maps_indicator_current_position.png
index 4e427d8..7c6e5b8 100644
--- a/core/res/res/drawable-mdpi/ic_maps_indicator_current_position.png
+++ b/core/res/res/drawable-mdpi/ic_maps_indicator_current_position.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_maps_indicator_current_position_anim1.png b/core/res/res/drawable-mdpi/ic_maps_indicator_current_position_anim1.png
index 47bb9fa..138e6e7 100644
--- a/core/res/res/drawable-mdpi/ic_maps_indicator_current_position_anim1.png
+++ b/core/res/res/drawable-mdpi/ic_maps_indicator_current_position_anim1.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_maps_indicator_current_position_anim2.png b/core/res/res/drawable-mdpi/ic_maps_indicator_current_position_anim2.png
index b1167bc..2ce2fb5 100644
--- a/core/res/res/drawable-mdpi/ic_maps_indicator_current_position_anim2.png
+++ b/core/res/res/drawable-mdpi/ic_maps_indicator_current_position_anim2.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_maps_indicator_current_position_anim3.png b/core/res/res/drawable-mdpi/ic_maps_indicator_current_position_anim3.png
index f681a4c..385d395 100644
--- a/core/res/res/drawable-mdpi/ic_maps_indicator_current_position_anim3.png
+++ b/core/res/res/drawable-mdpi/ic_maps_indicator_current_position_anim3.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_embed_play.png b/core/res/res/drawable-mdpi/ic_media_embed_play.png
index 3576ce5..539631e 100644
--- a/core/res/res/drawable-mdpi/ic_media_embed_play.png
+++ b/core/res/res/drawable-mdpi/ic_media_embed_play.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_ff.png b/core/res/res/drawable-mdpi/ic_media_ff.png
index 170dd2d..38f2ac7 100644
--- a/core/res/res/drawable-mdpi/ic_media_ff.png
+++ b/core/res/res/drawable-mdpi/ic_media_ff.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_fullscreen.png b/core/res/res/drawable-mdpi/ic_media_fullscreen.png
index 960aa85..a07ff0b 100644
--- a/core/res/res/drawable-mdpi/ic_media_fullscreen.png
+++ b/core/res/res/drawable-mdpi/ic_media_fullscreen.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_next.png b/core/res/res/drawable-mdpi/ic_media_next.png
index fcd73d9..9d9a871 100644
--- a/core/res/res/drawable-mdpi/ic_media_next.png
+++ b/core/res/res/drawable-mdpi/ic_media_next.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_pause.png b/core/res/res/drawable-mdpi/ic_media_pause.png
index 3e6b2a1..efd69e5 100644
--- a/core/res/res/drawable-mdpi/ic_media_pause.png
+++ b/core/res/res/drawable-mdpi/ic_media_pause.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_play.png b/core/res/res/drawable-mdpi/ic_media_play.png
index 7966bbc..fe08373 100644
--- a/core/res/res/drawable-mdpi/ic_media_play.png
+++ b/core/res/res/drawable-mdpi/ic_media_play.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_previous.png b/core/res/res/drawable-mdpi/ic_media_previous.png
index b653d05..b933d07 100644
--- a/core/res/res/drawable-mdpi/ic_media_previous.png
+++ b/core/res/res/drawable-mdpi/ic_media_previous.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_rew.png b/core/res/res/drawable-mdpi/ic_media_rew.png
index 5489180..c4a2e25 100644
--- a/core/res/res/drawable-mdpi/ic_media_rew.png
+++ b/core/res/res/drawable-mdpi/ic_media_rew.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_01_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_01_mtrl.png
index ca1bf45..a781b53 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_01_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_01_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_02_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_02_mtrl.png
index 69611bc..fee3308 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_02_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_02_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_03_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_03_mtrl.png
index 53e0f64..e3281f6 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_03_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_03_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_04_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_04_mtrl.png
index bcf2a18..06a8e3d 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_04_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_04_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_06_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_06_mtrl.png
index 5a5e2d5..eac0742 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_06_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_06_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_07_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_07_mtrl.png
index 82cf33c..d3aed87 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_07_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_07_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_08_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_08_mtrl.png
index 522b331..93a58f3 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_08_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_08_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_09_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_09_mtrl.png
index 23723a3..7641cc1 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_09_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_09_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_10_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_10_mtrl.png
index 313b6d2..03fed80 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_10_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_10_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_11_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_11_mtrl.png
index cfbc110..9c930f3 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_11_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_11_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_12_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_12_mtrl.png
index 2b2c628..d1bc5b6 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_12_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_12_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_13_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_13_mtrl.png
index 260adca..c90dd22 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_13_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_13_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_14_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_14_mtrl.png
index cadb1c5d..894149d 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_14_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_14_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_15_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_15_mtrl.png
index b91e799..432d797 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_15_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_15_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_16_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_16_mtrl.png
index 19edb96..5f1770d 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_16_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_16_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_21_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_21_mtrl.png
index c51481a..1f23859 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_21_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_21_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_22_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_22_mtrl.png
index 80d09e2..bd39761 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_22_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_22_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_23_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_23_mtrl.png
index c4ad65f..6741ba7 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_23_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_23_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_26_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_26_mtrl.png
index 55c3959..7f696f4 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_26_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_26_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_29_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_29_mtrl.png
index a3164c9..63c26daf 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_29_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_29_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_30_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_30_mtrl.png
index b550760..d3eaa85 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_dark_30_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_dark_30_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_light_00_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_light_00_mtrl.png
index d5efab4..57ec5ff 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_light_00_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_light_00_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_light_01_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_light_01_mtrl.png
index 74d39ac..8b6cbc6 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_light_01_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_light_01_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_light_02_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_light_02_mtrl.png
index 3775cef..702927f 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_light_02_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_light_02_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_light_03_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_light_03_mtrl.png
index d960a39..c9cd323 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_light_03_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_light_03_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_light_04_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_light_04_mtrl.png
index 6101cdf..50526da7 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_light_04_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_light_04_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_light_05_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_light_05_mtrl.png
index fca6c96..262594f 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_light_05_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_light_05_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_light_06_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_light_06_mtrl.png
index b2bdc46..c53ec35 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_light_06_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_light_06_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_light_07_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_light_07_mtrl.png
index 9d8335e..a417d87 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_light_07_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_light_07_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_light_08_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_light_08_mtrl.png
index 4593765..f1eca9d 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_light_08_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_light_08_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_light_09_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_light_09_mtrl.png
index d740810..463ae89 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_light_09_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_light_09_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_light_10_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_light_10_mtrl.png
index 7b8a7fc..e3e4452 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_light_10_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_light_10_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_light_11_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_light_11_mtrl.png
index e5d3c682..b723d56 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_light_11_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_light_11_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_light_12_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_light_12_mtrl.png
index b264a99..b425a3c 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_light_12_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_light_12_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_light_13_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_light_13_mtrl.png
index 0232d72..a3ad515 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_light_13_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_light_13_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_light_14_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_light_14_mtrl.png
index 2aa94bb..aa27e4e 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_light_14_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_light_14_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_light_15_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_light_15_mtrl.png
index 693f6c6..a55c8c1 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_light_15_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_light_15_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_light_16_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_light_16_mtrl.png
index b7aea5c..311bbc6 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_light_16_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_light_16_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_light_17_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_light_17_mtrl.png
index 217cb3d..34dea41 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_light_17_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_light_17_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_light_18_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_light_18_mtrl.png
index 933f338..331423d 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_light_18_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_light_18_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_light_19_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_light_19_mtrl.png
index a2ced71..0f13e6e 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_light_19_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_light_19_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_light_20_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_light_20_mtrl.png
index 4303ca4..3762379 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_light_20_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_light_20_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_light_21_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_light_21_mtrl.png
index c4d95597..3e9d021 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_light_21_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_light_21_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_light_22_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_light_22_mtrl.png
index a6e278b..213a022 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_light_22_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_light_22_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_light_23_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_light_23_mtrl.png
index 19bf6c2..e84d0be 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_light_23_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_light_23_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_light_24_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_light_24_mtrl.png
index c6c2163..7dc09bc 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_light_24_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_light_24_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_light_25_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_light_25_mtrl.png
index fe87238..802d331 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_light_25_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_light_25_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_light_26_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_light_26_mtrl.png
index 229c489..5fa4394 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_light_26_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_light_26_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_light_27_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_light_27_mtrl.png
index 64155d9..2cedee7 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_light_27_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_light_27_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_light_28_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_light_28_mtrl.png
index cb4c0ed..247ac15 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_light_28_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_light_28_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_light_29_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_light_29_mtrl.png
index a85c70c..a1fb7b5 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_light_29_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_light_29_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connected_light_30_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connected_light_30_mtrl.png
index d99afbf..9dbd31e 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connected_light_30_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connected_light_30_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_01_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_01_mtrl.png
index ca1bf45..a781b53 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_01_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_01_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_02_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_02_mtrl.png
index 69611bc..fee3308 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_02_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_02_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_03_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_03_mtrl.png
index 53e0f64..e3281f6 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_03_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_03_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_04_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_04_mtrl.png
index bcf2a18..06a8e3d 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_04_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_04_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_06_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_06_mtrl.png
index 5a5e2d5..eac0742 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_06_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_06_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_07_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_07_mtrl.png
index 82cf33c..d3aed87 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_07_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_07_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_08_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_08_mtrl.png
index 522b331..93a58f3 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_08_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_08_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_09_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_09_mtrl.png
index 23723a3..7641cc1 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_09_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_09_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_10_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_10_mtrl.png
index 313b6d2..03fed80 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_10_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_10_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_11_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_11_mtrl.png
index db37fc5..744fb13 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_11_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_11_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_12_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_12_mtrl.png
index 79941dc..67586de 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_12_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_12_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_13_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_13_mtrl.png
index 3361fe2..5cfce62 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_13_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_13_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_14_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_14_mtrl.png
index 5649d0f..a488034 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_14_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_14_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_15_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_15_mtrl.png
index 801b562..039f99e 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_15_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_15_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_16_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_16_mtrl.png
index 38e1408..e610da5 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_16_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_16_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_17_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_17_mtrl.png
index f99797d..1d8b1afa 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_17_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_17_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_18_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_18_mtrl.png
index 7048711..22c6965 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_18_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_18_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_20_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_20_mtrl.png
index da3a23b..04c3ca9 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_20_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_20_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_21_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_21_mtrl.png
index 4007ed1..22e2405 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_21_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_21_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_22_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_22_mtrl.png
index 518d2b9..43dc3d5 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_22_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_22_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_23_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_23_mtrl.png
index d821697..e75f5b2 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_23_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_23_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_24_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_24_mtrl.png
index aa196081..b2010d15 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_24_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_24_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_25_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_25_mtrl.png
index 81bf08c..60fac0f 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_25_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_25_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_26_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_26_mtrl.png
index 1bb7aec..f507b65 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_26_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_26_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_27_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_27_mtrl.png
index 864795c..13fef4d 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_27_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_27_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_28_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_28_mtrl.png
index ed07e9f..8a76de1 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_28_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_28_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_29_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_29_mtrl.png
index a188260..34ad144 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_29_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_dark_29_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_00_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_00_mtrl.png
index d5efab4..57ec5ff 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_00_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_00_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_01_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_01_mtrl.png
index 74d39ac..8b6cbc6 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_01_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_01_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_02_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_02_mtrl.png
index 3775cef..702927f 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_02_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_02_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_03_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_03_mtrl.png
index d960a39..c9cd323 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_03_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_03_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_04_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_04_mtrl.png
index 6101cdf..50526da7 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_04_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_04_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_05_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_05_mtrl.png
index fca6c96..262594f 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_05_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_05_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_06_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_06_mtrl.png
index b2bdc46..c53ec35 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_06_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_06_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_07_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_07_mtrl.png
index 9d8335e..a417d87 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_07_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_07_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_08_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_08_mtrl.png
index 4593765..f1eca9d 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_08_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_08_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_09_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_09_mtrl.png
index d740810..463ae89 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_09_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_09_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_10_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_10_mtrl.png
index 7b8a7fc..e3e4452 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_10_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_10_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_11_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_11_mtrl.png
index aadb0cd..42d6e7c 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_11_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_11_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_12_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_12_mtrl.png
index 628e63d..d658d3c 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_12_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_12_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_13_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_13_mtrl.png
index dfc63ae..11b3e7e 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_13_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_13_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_14_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_14_mtrl.png
index 450ead1..de090f3 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_14_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_14_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_15_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_15_mtrl.png
index 6424958..2c03c4d 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_15_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_15_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_16_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_16_mtrl.png
index c5b7fa4..715a57d 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_16_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_16_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_17_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_17_mtrl.png
index 13fcf6f..58d14b3 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_17_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_17_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_18_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_18_mtrl.png
index 5be9c69..c69cb24 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_18_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_18_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_19_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_19_mtrl.png
index 3de2194..b4cdf3f 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_19_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_19_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_20_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_20_mtrl.png
index c40a2cf..2fed6f6 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_20_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_20_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_21_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_21_mtrl.png
index 9923ccd..d5ec95d 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_21_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_21_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_22_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_22_mtrl.png
index 8a000c1..4ae3f4d 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_22_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_22_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_23_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_23_mtrl.png
index 3680ced..61631c6 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_23_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_23_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_24_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_24_mtrl.png
index d014f5e..b6527c0 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_24_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_24_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_25_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_25_mtrl.png
index a8aefdb..7aad1b8 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_25_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_25_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_26_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_26_mtrl.png
index 4716d66..bbbd728 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_26_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_26_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_27_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_27_mtrl.png
index fdeaf4f..8c19981 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_27_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_27_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_28_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_28_mtrl.png
index 9accc7a..9e70c35 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_28_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_28_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_29_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_29_mtrl.png
index 1f0a327..731928f 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_29_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_29_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_30_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_30_mtrl.png
index d5efab4..57ec5ff 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_connecting_light_30_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_connecting_light_30_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_disabled_holo_dark.png b/core/res/res/drawable-mdpi/ic_media_route_disabled_holo_dark.png
index 52e3a5a..de6635e 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_disabled_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_disabled_holo_light.png b/core/res/res/drawable-mdpi/ic_media_route_disabled_holo_light.png
index 319c57e..99a52fe 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_disabled_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_disabled_mtrl_alpha.png b/core/res/res/drawable-mdpi/ic_media_route_disabled_mtrl_alpha.png
index ec43047..0fb0a24 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_disabled_mtrl_alpha.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_disabled_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_off_dark_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_off_dark_mtrl.png
index 9ef3ea6..fdc064f 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_off_dark_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_off_dark_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_off_holo_dark.png b/core/res/res/drawable-mdpi/ic_media_route_off_holo_dark.png
index f98c0a85..8b2b70e 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_off_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_off_holo_light.png b/core/res/res/drawable-mdpi/ic_media_route_off_holo_light.png
index b74cdb5..4eae5b6 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_off_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_off_light_mtrl.png b/core/res/res/drawable-mdpi/ic_media_route_off_light_mtrl.png
index cbcc75a..f0b8c52 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_off_light_mtrl.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_off_light_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_0_holo_dark.png b/core/res/res/drawable-mdpi/ic_media_route_on_0_holo_dark.png
index a6a4bd0..646c4e5 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_on_0_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_0_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_0_holo_light.png b/core/res/res/drawable-mdpi/ic_media_route_on_0_holo_light.png
index 106fd3a..dcee05c 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_on_0_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_0_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_1_holo_dark.png b/core/res/res/drawable-mdpi/ic_media_route_on_1_holo_dark.png
index 2c141ab..8fc3b53 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_on_1_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_1_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_1_holo_light.png b/core/res/res/drawable-mdpi/ic_media_route_on_1_holo_light.png
index 0b62d0b..c2f9865 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_on_1_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_1_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_2_holo_dark.png b/core/res/res/drawable-mdpi/ic_media_route_on_2_holo_dark.png
index 23442b0..4185cea 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_on_2_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_2_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_2_holo_light.png b/core/res/res/drawable-mdpi/ic_media_route_on_2_holo_light.png
index 42b329f..b4d7813 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_on_2_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_2_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_holo_dark.png b/core/res/res/drawable-mdpi/ic_media_route_on_holo_dark.png
index 58ff506..f688efe 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_on_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_holo_light.png b/core/res/res/drawable-mdpi/ic_media_route_on_holo_light.png
index 25257f8..bf3d886 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_on_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_stop.png b/core/res/res/drawable-mdpi/ic_media_stop.png
index 8ea7efee..eb15a4c 100644
--- a/core/res/res/drawable-mdpi/ic_media_stop.png
+++ b/core/res/res/drawable-mdpi/ic_media_stop.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_video_poster.png b/core/res/res/drawable-mdpi/ic_media_video_poster.png
index f457f23..647ee9c 100644
--- a/core/res/res/drawable-mdpi/ic_media_video_poster.png
+++ b/core/res/res/drawable-mdpi/ic_media_video_poster.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_account_list.png b/core/res/res/drawable-mdpi/ic_menu_account_list.png
index e4e717e..12c3181 100644
--- a/core/res/res/drawable-mdpi/ic_menu_account_list.png
+++ b/core/res/res/drawable-mdpi/ic_menu_account_list.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_add.png b/core/res/res/drawable-mdpi/ic_menu_add.png
index 361c7c4..062af67 100644
--- a/core/res/res/drawable-mdpi/ic_menu_add.png
+++ b/core/res/res/drawable-mdpi/ic_menu_add.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_agenda.png b/core/res/res/drawable-mdpi/ic_menu_agenda.png
index c63a12bf..d6082d6 100644
--- a/core/res/res/drawable-mdpi/ic_menu_agenda.png
+++ b/core/res/res/drawable-mdpi/ic_menu_agenda.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_allfriends.png b/core/res/res/drawable-mdpi/ic_menu_allfriends.png
index 45256d1..7223a0c 100644
--- a/core/res/res/drawable-mdpi/ic_menu_allfriends.png
+++ b/core/res/res/drawable-mdpi/ic_menu_allfriends.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_always_landscape_portrait.png b/core/res/res/drawable-mdpi/ic_menu_always_landscape_portrait.png
index f9f475a..eea6f03 100644
--- a/core/res/res/drawable-mdpi/ic_menu_always_landscape_portrait.png
+++ b/core/res/res/drawable-mdpi/ic_menu_always_landscape_portrait.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_archive.png b/core/res/res/drawable-mdpi/ic_menu_archive.png
index 49ac569..db59091 100644
--- a/core/res/res/drawable-mdpi/ic_menu_archive.png
+++ b/core/res/res/drawable-mdpi/ic_menu_archive.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_attachment.png b/core/res/res/drawable-mdpi/ic_menu_attachment.png
index d3d4812..cbcc3c3 100644
--- a/core/res/res/drawable-mdpi/ic_menu_attachment.png
+++ b/core/res/res/drawable-mdpi/ic_menu_attachment.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_back.png b/core/res/res/drawable-mdpi/ic_menu_back.png
index bb69245..a5812a0 100644
--- a/core/res/res/drawable-mdpi/ic_menu_back.png
+++ b/core/res/res/drawable-mdpi/ic_menu_back.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_block.png b/core/res/res/drawable-mdpi/ic_menu_block.png
index 63f952d..30589d2 100644
--- a/core/res/res/drawable-mdpi/ic_menu_block.png
+++ b/core/res/res/drawable-mdpi/ic_menu_block.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_blocked_user.png b/core/res/res/drawable-mdpi/ic_menu_blocked_user.png
index ac8cc10..c6a58ee 100644
--- a/core/res/res/drawable-mdpi/ic_menu_blocked_user.png
+++ b/core/res/res/drawable-mdpi/ic_menu_blocked_user.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_btn_add.png b/core/res/res/drawable-mdpi/ic_menu_btn_add.png
index 361c7c4..062af67 100644
--- a/core/res/res/drawable-mdpi/ic_menu_btn_add.png
+++ b/core/res/res/drawable-mdpi/ic_menu_btn_add.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_call.png b/core/res/res/drawable-mdpi/ic_menu_call.png
index b7ee91a..b1c98b0 100644
--- a/core/res/res/drawable-mdpi/ic_menu_call.png
+++ b/core/res/res/drawable-mdpi/ic_menu_call.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_camera.png b/core/res/res/drawable-mdpi/ic_menu_camera.png
index f8cf93c..2db27a0 100644
--- a/core/res/res/drawable-mdpi/ic_menu_camera.png
+++ b/core/res/res/drawable-mdpi/ic_menu_camera.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_cc_am.png b/core/res/res/drawable-mdpi/ic_menu_cc_am.png
index 8e2ba09..1d56fea 100644
--- a/core/res/res/drawable-mdpi/ic_menu_cc_am.png
+++ b/core/res/res/drawable-mdpi/ic_menu_cc_am.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_chat_dashboard.png b/core/res/res/drawable-mdpi/ic_menu_chat_dashboard.png
index 14b7482..aeb48fc 100644
--- a/core/res/res/drawable-mdpi/ic_menu_chat_dashboard.png
+++ b/core/res/res/drawable-mdpi/ic_menu_chat_dashboard.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_clear_playlist.png b/core/res/res/drawable-mdpi/ic_menu_clear_playlist.png
index 9100a69..1331960 100644
--- a/core/res/res/drawable-mdpi/ic_menu_clear_playlist.png
+++ b/core/res/res/drawable-mdpi/ic_menu_clear_playlist.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_close_clear_cancel.png b/core/res/res/drawable-mdpi/ic_menu_close_clear_cancel.png
index 1161a7c..b2b88a9 100644
--- a/core/res/res/drawable-mdpi/ic_menu_close_clear_cancel.png
+++ b/core/res/res/drawable-mdpi/ic_menu_close_clear_cancel.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_compass.png b/core/res/res/drawable-mdpi/ic_menu_compass.png
index 25235cc..5458ba6 100644
--- a/core/res/res/drawable-mdpi/ic_menu_compass.png
+++ b/core/res/res/drawable-mdpi/ic_menu_compass.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_compose.png b/core/res/res/drawable-mdpi/ic_menu_compose.png
index a911141..8e4f9a1 100644
--- a/core/res/res/drawable-mdpi/ic_menu_compose.png
+++ b/core/res/res/drawable-mdpi/ic_menu_compose.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_copy.png b/core/res/res/drawable-mdpi/ic_menu_copy.png
index eee5540..6237e0f 100644
--- a/core/res/res/drawable-mdpi/ic_menu_copy.png
+++ b/core/res/res/drawable-mdpi/ic_menu_copy.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_copy_holo_dark.png b/core/res/res/drawable-mdpi/ic_menu_copy_holo_dark.png
index 97e8ac1..3e46fa7 100644
--- a/core/res/res/drawable-mdpi/ic_menu_copy_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_menu_copy_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_copy_holo_light.png b/core/res/res/drawable-mdpi/ic_menu_copy_holo_light.png
index 74cb920..3874542 100644
--- a/core/res/res/drawable-mdpi/ic_menu_copy_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_menu_copy_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_crop.png b/core/res/res/drawable-mdpi/ic_menu_crop.png
index 30e40cf..f04b159 100644
--- a/core/res/res/drawable-mdpi/ic_menu_crop.png
+++ b/core/res/res/drawable-mdpi/ic_menu_crop.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_cut.png b/core/res/res/drawable-mdpi/ic_menu_cut.png
index 865d1e0..c30a384 100644
--- a/core/res/res/drawable-mdpi/ic_menu_cut.png
+++ b/core/res/res/drawable-mdpi/ic_menu_cut.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_cut_holo_dark.png b/core/res/res/drawable-mdpi/ic_menu_cut_holo_dark.png
index baa5427..2edfb12 100644
--- a/core/res/res/drawable-mdpi/ic_menu_cut_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_menu_cut_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_cut_holo_light.png b/core/res/res/drawable-mdpi/ic_menu_cut_holo_light.png
index 8e6a93f..13ef5c7 100644
--- a/core/res/res/drawable-mdpi/ic_menu_cut_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_menu_cut_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_day.png b/core/res/res/drawable-mdpi/ic_menu_day.png
index 88bc348..94ef0f2 100644
--- a/core/res/res/drawable-mdpi/ic_menu_day.png
+++ b/core/res/res/drawable-mdpi/ic_menu_day.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_delete.png b/core/res/res/drawable-mdpi/ic_menu_delete.png
index e2c8700..bb9cc8b 100644
--- a/core/res/res/drawable-mdpi/ic_menu_delete.png
+++ b/core/res/res/drawable-mdpi/ic_menu_delete.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_directions.png b/core/res/res/drawable-mdpi/ic_menu_directions.png
index d10e0b1..c53f7e2 100644
--- a/core/res/res/drawable-mdpi/ic_menu_directions.png
+++ b/core/res/res/drawable-mdpi/ic_menu_directions.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_edit.png b/core/res/res/drawable-mdpi/ic_menu_edit.png
index d0314e98..045d4e4 100644
--- a/core/res/res/drawable-mdpi/ic_menu_edit.png
+++ b/core/res/res/drawable-mdpi/ic_menu_edit.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_emoticons.png b/core/res/res/drawable-mdpi/ic_menu_emoticons.png
index 8d1780f..d1b2aba 100644
--- a/core/res/res/drawable-mdpi/ic_menu_emoticons.png
+++ b/core/res/res/drawable-mdpi/ic_menu_emoticons.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_end_conversation.png b/core/res/res/drawable-mdpi/ic_menu_end_conversation.png
index fb9f153..34a9a767 100644
--- a/core/res/res/drawable-mdpi/ic_menu_end_conversation.png
+++ b/core/res/res/drawable-mdpi/ic_menu_end_conversation.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_find.png b/core/res/res/drawable-mdpi/ic_menu_find.png
index 82dcba7..7cf44a0 100644
--- a/core/res/res/drawable-mdpi/ic_menu_find.png
+++ b/core/res/res/drawable-mdpi/ic_menu_find.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_find_holo_dark.png b/core/res/res/drawable-mdpi/ic_menu_find_holo_dark.png
index 45f8fd3..c7832e2 100644
--- a/core/res/res/drawable-mdpi/ic_menu_find_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_menu_find_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_find_holo_light.png b/core/res/res/drawable-mdpi/ic_menu_find_holo_light.png
index 9033f1e..776996c 100644
--- a/core/res/res/drawable-mdpi/ic_menu_find_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_menu_find_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_find_mtrl_alpha.png b/core/res/res/drawable-mdpi/ic_menu_find_mtrl_alpha.png
index 6be897d..3328952 100644
--- a/core/res/res/drawable-mdpi/ic_menu_find_mtrl_alpha.png
+++ b/core/res/res/drawable-mdpi/ic_menu_find_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_forward.png b/core/res/res/drawable-mdpi/ic_menu_forward.png
index 4a0b6ef..515da21 100644
--- a/core/res/res/drawable-mdpi/ic_menu_forward.png
+++ b/core/res/res/drawable-mdpi/ic_menu_forward.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_friendslist.png b/core/res/res/drawable-mdpi/ic_menu_friendslist.png
index 8a29be3b..de0b56b 100644
--- a/core/res/res/drawable-mdpi/ic_menu_friendslist.png
+++ b/core/res/res/drawable-mdpi/ic_menu_friendslist.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_gallery.png b/core/res/res/drawable-mdpi/ic_menu_gallery.png
index d3a0200..009437d 100644
--- a/core/res/res/drawable-mdpi/ic_menu_gallery.png
+++ b/core/res/res/drawable-mdpi/ic_menu_gallery.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_goto.png b/core/res/res/drawable-mdpi/ic_menu_goto.png
index 5471f5b..d00a964 100644
--- a/core/res/res/drawable-mdpi/ic_menu_goto.png
+++ b/core/res/res/drawable-mdpi/ic_menu_goto.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_help.png b/core/res/res/drawable-mdpi/ic_menu_help.png
index dd24845..bffc194 100644
--- a/core/res/res/drawable-mdpi/ic_menu_help.png
+++ b/core/res/res/drawable-mdpi/ic_menu_help.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_help_holo_light.png b/core/res/res/drawable-mdpi/ic_menu_help_holo_light.png
index 010577f..0453a8a 100644
--- a/core/res/res/drawable-mdpi/ic_menu_help_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_menu_help_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_home.png b/core/res/res/drawable-mdpi/ic_menu_home.png
index f19f58d..4674cdc 100644
--- a/core/res/res/drawable-mdpi/ic_menu_home.png
+++ b/core/res/res/drawable-mdpi/ic_menu_home.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_info_details.png b/core/res/res/drawable-mdpi/ic_menu_info_details.png
index 18b15b5a..5cd26a3 100644
--- a/core/res/res/drawable-mdpi/ic_menu_info_details.png
+++ b/core/res/res/drawable-mdpi/ic_menu_info_details.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_invite.png b/core/res/res/drawable-mdpi/ic_menu_invite.png
index aa1898d..979400b 100644
--- a/core/res/res/drawable-mdpi/ic_menu_invite.png
+++ b/core/res/res/drawable-mdpi/ic_menu_invite.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_login.png b/core/res/res/drawable-mdpi/ic_menu_login.png
index 122ba33..099fcf8 100644
--- a/core/res/res/drawable-mdpi/ic_menu_login.png
+++ b/core/res/res/drawable-mdpi/ic_menu_login.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_manage.png b/core/res/res/drawable-mdpi/ic_menu_manage.png
index 8d3a9fa..cc90218 100644
--- a/core/res/res/drawable-mdpi/ic_menu_manage.png
+++ b/core/res/res/drawable-mdpi/ic_menu_manage.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_mapmode.png b/core/res/res/drawable-mdpi/ic_menu_mapmode.png
index 1b50b5a..97eb125 100644
--- a/core/res/res/drawable-mdpi/ic_menu_mapmode.png
+++ b/core/res/res/drawable-mdpi/ic_menu_mapmode.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_mark.png b/core/res/res/drawable-mdpi/ic_menu_mark.png
index 0c55506..8ec1b53 100644
--- a/core/res/res/drawable-mdpi/ic_menu_mark.png
+++ b/core/res/res/drawable-mdpi/ic_menu_mark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_month.png b/core/res/res/drawable-mdpi/ic_menu_month.png
index ff201df..9d58986 100644
--- a/core/res/res/drawable-mdpi/ic_menu_month.png
+++ b/core/res/res/drawable-mdpi/ic_menu_month.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_more.png b/core/res/res/drawable-mdpi/ic_menu_more.png
index 263fef8..69bf74d 100644
--- a/core/res/res/drawable-mdpi/ic_menu_more.png
+++ b/core/res/res/drawable-mdpi/ic_menu_more.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_moreoverflow.png b/core/res/res/drawable-mdpi/ic_menu_moreoverflow.png
index e478922..fa4e74e 100644
--- a/core/res/res/drawable-mdpi/ic_menu_moreoverflow.png
+++ b/core/res/res/drawable-mdpi/ic_menu_moreoverflow.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_moreoverflow_focused_holo_dark.png b/core/res/res/drawable-mdpi/ic_menu_moreoverflow_focused_holo_dark.png
index 48d6c78..ae81777 100644
--- a/core/res/res/drawable-mdpi/ic_menu_moreoverflow_focused_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_menu_moreoverflow_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_moreoverflow_focused_holo_light.png b/core/res/res/drawable-mdpi/ic_menu_moreoverflow_focused_holo_light.png
index 50ff8fc..849c763 100644
--- a/core/res/res/drawable-mdpi/ic_menu_moreoverflow_focused_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_menu_moreoverflow_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_dark.png b/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_dark.png
index ba704b6..3a6966c 100644
--- a/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_light.png b/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_light.png
index 01d6816..bef7cea 100644
--- a/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_my_calendar.png b/core/res/res/drawable-mdpi/ic_menu_my_calendar.png
index 991dfb0..28ea2ec 100644
--- a/core/res/res/drawable-mdpi/ic_menu_my_calendar.png
+++ b/core/res/res/drawable-mdpi/ic_menu_my_calendar.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_mylocation.png b/core/res/res/drawable-mdpi/ic_menu_mylocation.png
index 2a61a97..8529145 100644
--- a/core/res/res/drawable-mdpi/ic_menu_mylocation.png
+++ b/core/res/res/drawable-mdpi/ic_menu_mylocation.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_myplaces.png b/core/res/res/drawable-mdpi/ic_menu_myplaces.png
index 75f2c9b..0384f5c 100644
--- a/core/res/res/drawable-mdpi/ic_menu_myplaces.png
+++ b/core/res/res/drawable-mdpi/ic_menu_myplaces.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_notifications.png b/core/res/res/drawable-mdpi/ic_menu_notifications.png
index 2474d56..47c8f75 100644
--- a/core/res/res/drawable-mdpi/ic_menu_notifications.png
+++ b/core/res/res/drawable-mdpi/ic_menu_notifications.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_paste.png b/core/res/res/drawable-mdpi/ic_menu_paste.png
index 8c9916c..d36c48b 100644
--- a/core/res/res/drawable-mdpi/ic_menu_paste.png
+++ b/core/res/res/drawable-mdpi/ic_menu_paste.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_paste_holo_dark.png b/core/res/res/drawable-mdpi/ic_menu_paste_holo_dark.png
index 093496d..4400a9e 100644
--- a/core/res/res/drawable-mdpi/ic_menu_paste_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_menu_paste_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_paste_holo_light.png b/core/res/res/drawable-mdpi/ic_menu_paste_holo_light.png
index 61fd91c..1147f19 100644
--- a/core/res/res/drawable-mdpi/ic_menu_paste_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_menu_paste_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_play_clip.png b/core/res/res/drawable-mdpi/ic_menu_play_clip.png
index 5983c22..b9fec48 100644
--- a/core/res/res/drawable-mdpi/ic_menu_play_clip.png
+++ b/core/res/res/drawable-mdpi/ic_menu_play_clip.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_preferences.png b/core/res/res/drawable-mdpi/ic_menu_preferences.png
index ccc50e6..0387871 100644
--- a/core/res/res/drawable-mdpi/ic_menu_preferences.png
+++ b/core/res/res/drawable-mdpi/ic_menu_preferences.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_recent_history.png b/core/res/res/drawable-mdpi/ic_menu_recent_history.png
index e5f8e2d..4033567 100644
--- a/core/res/res/drawable-mdpi/ic_menu_recent_history.png
+++ b/core/res/res/drawable-mdpi/ic_menu_recent_history.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_report_image.png b/core/res/res/drawable-mdpi/ic_menu_report_image.png
index 414b0ae..4b0e3ef 100644
--- a/core/res/res/drawable-mdpi/ic_menu_report_image.png
+++ b/core/res/res/drawable-mdpi/ic_menu_report_image.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_revert.png b/core/res/res/drawable-mdpi/ic_menu_revert.png
index 7a45163..71d1ef4 100644
--- a/core/res/res/drawable-mdpi/ic_menu_revert.png
+++ b/core/res/res/drawable-mdpi/ic_menu_revert.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_rotate.png b/core/res/res/drawable-mdpi/ic_menu_rotate.png
index 35fa56d..88b83b9 100644
--- a/core/res/res/drawable-mdpi/ic_menu_rotate.png
+++ b/core/res/res/drawable-mdpi/ic_menu_rotate.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_save.png b/core/res/res/drawable-mdpi/ic_menu_save.png
index 5f66864..edce0e3 100644
--- a/core/res/res/drawable-mdpi/ic_menu_save.png
+++ b/core/res/res/drawable-mdpi/ic_menu_save.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_search.png b/core/res/res/drawable-mdpi/ic_menu_search.png
index d18f542..7c380bc 100644
--- a/core/res/res/drawable-mdpi/ic_menu_search.png
+++ b/core/res/res/drawable-mdpi/ic_menu_search.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_search_holo_dark.png b/core/res/res/drawable-mdpi/ic_menu_search_holo_dark.png
index 906da53..b40eb5c 100644
--- a/core/res/res/drawable-mdpi/ic_menu_search_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_menu_search_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_search_holo_light.png b/core/res/res/drawable-mdpi/ic_menu_search_holo_light.png
index 0350a43..fc166d3 100644
--- a/core/res/res/drawable-mdpi/ic_menu_search_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_menu_search_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_search_mtrl_alpha.png b/core/res/res/drawable-mdpi/ic_menu_search_mtrl_alpha.png
index 0fb57b2..f2a43ea 100644
--- a/core/res/res/drawable-mdpi/ic_menu_search_mtrl_alpha.png
+++ b/core/res/res/drawable-mdpi/ic_menu_search_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_selectall_holo_dark.png b/core/res/res/drawable-mdpi/ic_menu_selectall_holo_dark.png
index da64c75..538c19f 100644
--- a/core/res/res/drawable-mdpi/ic_menu_selectall_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_menu_selectall_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_selectall_holo_light.png b/core/res/res/drawable-mdpi/ic_menu_selectall_holo_light.png
index e0dd67c..b9ba075 100644
--- a/core/res/res/drawable-mdpi/ic_menu_selectall_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_menu_selectall_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_send.png b/core/res/res/drawable-mdpi/ic_menu_send.png
index 06b4717..8f81989 100644
--- a/core/res/res/drawable-mdpi/ic_menu_send.png
+++ b/core/res/res/drawable-mdpi/ic_menu_send.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_set_as.png b/core/res/res/drawable-mdpi/ic_menu_set_as.png
index 98cc305..4a07ba3 100644
--- a/core/res/res/drawable-mdpi/ic_menu_set_as.png
+++ b/core/res/res/drawable-mdpi/ic_menu_set_as.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_settings_holo_light.png b/core/res/res/drawable-mdpi/ic_menu_settings_holo_light.png
index f32a37e..4ab0afb 100644
--- a/core/res/res/drawable-mdpi/ic_menu_settings_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_menu_settings_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_share.png b/core/res/res/drawable-mdpi/ic_menu_share.png
index d89ca5f..a360b60 100644
--- a/core/res/res/drawable-mdpi/ic_menu_share.png
+++ b/core/res/res/drawable-mdpi/ic_menu_share.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_share_holo_dark.png b/core/res/res/drawable-mdpi/ic_menu_share_holo_dark.png
index 6bf21e3..beb875d 100644
--- a/core/res/res/drawable-mdpi/ic_menu_share_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_menu_share_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_share_holo_light.png b/core/res/res/drawable-mdpi/ic_menu_share_holo_light.png
index 70fe31a..3ebf848 100644
--- a/core/res/res/drawable-mdpi/ic_menu_share_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_menu_share_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_slideshow.png b/core/res/res/drawable-mdpi/ic_menu_slideshow.png
index 72bfcd9..3fbb6b2 100644
--- a/core/res/res/drawable-mdpi/ic_menu_slideshow.png
+++ b/core/res/res/drawable-mdpi/ic_menu_slideshow.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_sort_alphabetically.png b/core/res/res/drawable-mdpi/ic_menu_sort_alphabetically.png
index 0c5ffad..78ac265 100644
--- a/core/res/res/drawable-mdpi/ic_menu_sort_alphabetically.png
+++ b/core/res/res/drawable-mdpi/ic_menu_sort_alphabetically.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_sort_by_size.png b/core/res/res/drawable-mdpi/ic_menu_sort_by_size.png
index 19e8d1b..ecfe02f 100644
--- a/core/res/res/drawable-mdpi/ic_menu_sort_by_size.png
+++ b/core/res/res/drawable-mdpi/ic_menu_sort_by_size.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_star.png b/core/res/res/drawable-mdpi/ic_menu_star.png
index 0c22fe8..c641b42 100644
--- a/core/res/res/drawable-mdpi/ic_menu_star.png
+++ b/core/res/res/drawable-mdpi/ic_menu_star.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_start_conversation.png b/core/res/res/drawable-mdpi/ic_menu_start_conversation.png
index 24b6540..0ed1c89 100644
--- a/core/res/res/drawable-mdpi/ic_menu_start_conversation.png
+++ b/core/res/res/drawable-mdpi/ic_menu_start_conversation.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_stop.png b/core/res/res/drawable-mdpi/ic_menu_stop.png
index efb4036..077f09b 100644
--- a/core/res/res/drawable-mdpi/ic_menu_stop.png
+++ b/core/res/res/drawable-mdpi/ic_menu_stop.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_today.png b/core/res/res/drawable-mdpi/ic_menu_today.png
index 8c248ae..bc06e48 100644
--- a/core/res/res/drawable-mdpi/ic_menu_today.png
+++ b/core/res/res/drawable-mdpi/ic_menu_today.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_upload.png b/core/res/res/drawable-mdpi/ic_menu_upload.png
index 9e8459a..c5b9b24 100644
--- a/core/res/res/drawable-mdpi/ic_menu_upload.png
+++ b/core/res/res/drawable-mdpi/ic_menu_upload.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_upload_you_tube.png b/core/res/res/drawable-mdpi/ic_menu_upload_you_tube.png
index a67c409..d68e4ce 100644
--- a/core/res/res/drawable-mdpi/ic_menu_upload_you_tube.png
+++ b/core/res/res/drawable-mdpi/ic_menu_upload_you_tube.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_view.png b/core/res/res/drawable-mdpi/ic_menu_view.png
index 082810d..ff55f58 100644
--- a/core/res/res/drawable-mdpi/ic_menu_view.png
+++ b/core/res/res/drawable-mdpi/ic_menu_view.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_week.png b/core/res/res/drawable-mdpi/ic_menu_week.png
index e11e5f1..c2e51f9 100644
--- a/core/res/res/drawable-mdpi/ic_menu_week.png
+++ b/core/res/res/drawable-mdpi/ic_menu_week.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_zoom.png b/core/res/res/drawable-mdpi/ic_menu_zoom.png
index 062d6f3..66ff9f4 100644
--- a/core/res/res/drawable-mdpi/ic_menu_zoom.png
+++ b/core/res/res/drawable-mdpi/ic_menu_zoom.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_notification_cast_0.png b/core/res/res/drawable-mdpi/ic_notification_cast_0.png
index a51a3cb..fc2b88d 100644
--- a/core/res/res/drawable-mdpi/ic_notification_cast_0.png
+++ b/core/res/res/drawable-mdpi/ic_notification_cast_0.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_notification_cast_1.png b/core/res/res/drawable-mdpi/ic_notification_cast_1.png
index e081367..efe0e27 100644
--- a/core/res/res/drawable-mdpi/ic_notification_cast_1.png
+++ b/core/res/res/drawable-mdpi/ic_notification_cast_1.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_notification_cast_2.png b/core/res/res/drawable-mdpi/ic_notification_cast_2.png
index a7f4de4..80700220 100644
--- a/core/res/res/drawable-mdpi/ic_notification_cast_2.png
+++ b/core/res/res/drawable-mdpi/ic_notification_cast_2.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_notification_clear_all.png b/core/res/res/drawable-mdpi/ic_notification_clear_all.png
index f2114d7..e1a0333 100644
--- a/core/res/res/drawable-mdpi/ic_notification_clear_all.png
+++ b/core/res/res/drawable-mdpi/ic_notification_clear_all.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_notification_overlay.9.png b/core/res/res/drawable-mdpi/ic_notification_overlay.9.png
index 1a3063c4..be30492 100644
--- a/core/res/res/drawable-mdpi/ic_notification_overlay.9.png
+++ b/core/res/res/drawable-mdpi/ic_notification_overlay.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_partial_secure.png b/core/res/res/drawable-mdpi/ic_partial_secure.png
index 76ba96a..f1a75c0 100644
--- a/core/res/res/drawable-mdpi/ic_partial_secure.png
+++ b/core/res/res/drawable-mdpi/ic_partial_secure.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_popup_disk_full.png b/core/res/res/drawable-mdpi/ic_popup_disk_full.png
index e6da5d0..c7fe8063 100644
--- a/core/res/res/drawable-mdpi/ic_popup_disk_full.png
+++ b/core/res/res/drawable-mdpi/ic_popup_disk_full.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_popup_reminder.png b/core/res/res/drawable-mdpi/ic_popup_reminder.png
index af15279..0392b20 100644
--- a/core/res/res/drawable-mdpi/ic_popup_reminder.png
+++ b/core/res/res/drawable-mdpi/ic_popup_reminder.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_popup_sync_1.png b/core/res/res/drawable-mdpi/ic_popup_sync_1.png
index 13d8cdd..7945255 100644
--- a/core/res/res/drawable-mdpi/ic_popup_sync_1.png
+++ b/core/res/res/drawable-mdpi/ic_popup_sync_1.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_popup_sync_2.png b/core/res/res/drawable-mdpi/ic_popup_sync_2.png
index 6ca162a..6518ffb 100644
--- a/core/res/res/drawable-mdpi/ic_popup_sync_2.png
+++ b/core/res/res/drawable-mdpi/ic_popup_sync_2.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_popup_sync_3.png b/core/res/res/drawable-mdpi/ic_popup_sync_3.png
index a7c21dd..4e44218 100644
--- a/core/res/res/drawable-mdpi/ic_popup_sync_3.png
+++ b/core/res/res/drawable-mdpi/ic_popup_sync_3.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_popup_sync_4.png b/core/res/res/drawable-mdpi/ic_popup_sync_4.png
index e9be04e..f85a8dd 100644
--- a/core/res/res/drawable-mdpi/ic_popup_sync_4.png
+++ b/core/res/res/drawable-mdpi/ic_popup_sync_4.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_popup_sync_5.png b/core/res/res/drawable-mdpi/ic_popup_sync_5.png
index 65d87c4..f369d98 100644
--- a/core/res/res/drawable-mdpi/ic_popup_sync_5.png
+++ b/core/res/res/drawable-mdpi/ic_popup_sync_5.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_popup_sync_6.png b/core/res/res/drawable-mdpi/ic_popup_sync_6.png
index 2015c88..8c6a7ff 100644
--- a/core/res/res/drawable-mdpi/ic_popup_sync_6.png
+++ b/core/res/res/drawable-mdpi/ic_popup_sync_6.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_search.png b/core/res/res/drawable-mdpi/ic_search.png
index 66145e0..37cbde0 100644
--- a/core/res/res/drawable-mdpi/ic_search.png
+++ b/core/res/res/drawable-mdpi/ic_search.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_search_api_holo_dark.png b/core/res/res/drawable-mdpi/ic_search_api_holo_dark.png
index 4771a56..aeaf5e7 100644
--- a/core/res/res/drawable-mdpi/ic_search_api_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_search_api_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_search_api_holo_light.png b/core/res/res/drawable-mdpi/ic_search_api_holo_light.png
index 60a55f8..0636236 100644
--- a/core/res/res/drawable-mdpi/ic_search_api_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_search_api_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_search_category_default.png b/core/res/res/drawable-mdpi/ic_search_category_default.png
index 94446db..adc5d19 100644
--- a/core/res/res/drawable-mdpi/ic_search_category_default.png
+++ b/core/res/res/drawable-mdpi/ic_search_category_default.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_secure.png b/core/res/res/drawable-mdpi/ic_secure.png
index 4f15fc4..b85aafa 100644
--- a/core/res/res/drawable-mdpi/ic_secure.png
+++ b/core/res/res/drawable-mdpi/ic_secure.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_settings.png b/core/res/res/drawable-mdpi/ic_settings.png
index e6237eb..cd42919 100644
--- a/core/res/res/drawable-mdpi/ic_settings.png
+++ b/core/res/res/drawable-mdpi/ic_settings.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_settings_language.png b/core/res/res/drawable-mdpi/ic_settings_language.png
index f8aca67..c2eafb7 100644
--- a/core/res/res/drawable-mdpi/ic_settings_language.png
+++ b/core/res/res/drawable-mdpi/ic_settings_language.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_sim_card_multi_24px_clr.png b/core/res/res/drawable-mdpi/ic_sim_card_multi_24px_clr.png
index 5d21285..2e95c48 100644
--- a/core/res/res/drawable-mdpi/ic_sim_card_multi_24px_clr.png
+++ b/core/res/res/drawable-mdpi/ic_sim_card_multi_24px_clr.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_sim_card_multi_48px_clr.png b/core/res/res/drawable-mdpi/ic_sim_card_multi_48px_clr.png
index 249379d..24ad4f9 100644
--- a/core/res/res/drawable-mdpi/ic_sim_card_multi_48px_clr.png
+++ b/core/res/res/drawable-mdpi/ic_sim_card_multi_48px_clr.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_star_half_black_16dp.png b/core/res/res/drawable-mdpi/ic_star_half_black_16dp.png
index beea92a..cc2bb51 100644
--- a/core/res/res/drawable-mdpi/ic_star_half_black_16dp.png
+++ b/core/res/res/drawable-mdpi/ic_star_half_black_16dp.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_star_half_black_36dp.png b/core/res/res/drawable-mdpi/ic_star_half_black_36dp.png
index 5caae60..6101f0d 100644
--- a/core/res/res/drawable-mdpi/ic_star_half_black_36dp.png
+++ b/core/res/res/drawable-mdpi/ic_star_half_black_36dp.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_star_half_black_48dp.png b/core/res/res/drawable-mdpi/ic_star_half_black_48dp.png
index d53afa22..8e79e1c 100644
--- a/core/res/res/drawable-mdpi/ic_star_half_black_48dp.png
+++ b/core/res/res/drawable-mdpi/ic_star_half_black_48dp.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_sysbar_quicksettings.png b/core/res/res/drawable-mdpi/ic_sysbar_quicksettings.png
index 7928104..b8ffa44 100644
--- a/core/res/res/drawable-mdpi/ic_sysbar_quicksettings.png
+++ b/core/res/res/drawable-mdpi/ic_sysbar_quicksettings.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_vibrate.png b/core/res/res/drawable-mdpi/ic_vibrate.png
index 4fecce1..731269e 100644
--- a/core/res/res/drawable-mdpi/ic_vibrate.png
+++ b/core/res/res/drawable-mdpi/ic_vibrate.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_vibrate_small.png b/core/res/res/drawable-mdpi/ic_vibrate_small.png
index f04804e..e4126a7 100644
--- a/core/res/res/drawable-mdpi/ic_vibrate_small.png
+++ b/core/res/res/drawable-mdpi/ic_vibrate_small.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_voice_search.png b/core/res/res/drawable-mdpi/ic_voice_search.png
index b2535fb..764c663 100644
--- a/core/res/res/drawable-mdpi/ic_voice_search.png
+++ b/core/res/res/drawable-mdpi/ic_voice_search.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_voice_search_api_holo_dark.png b/core/res/res/drawable-mdpi/ic_voice_search_api_holo_dark.png
index fcc2105..e3e9945 100644
--- a/core/res/res/drawable-mdpi/ic_voice_search_api_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_voice_search_api_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_voice_search_api_holo_light.png b/core/res/res/drawable-mdpi/ic_voice_search_api_holo_light.png
index b516b95..957e321 100644
--- a/core/res/res/drawable-mdpi/ic_voice_search_api_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_voice_search_api_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_volume.png b/core/res/res/drawable-mdpi/ic_volume.png
index 20aa030..fb72781 100644
--- a/core/res/res/drawable-mdpi/ic_volume.png
+++ b/core/res/res/drawable-mdpi/ic_volume.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_volume_bluetooth_ad2p.png b/core/res/res/drawable-mdpi/ic_volume_bluetooth_ad2p.png
index cf86ab3..6360778 100644
--- a/core/res/res/drawable-mdpi/ic_volume_bluetooth_ad2p.png
+++ b/core/res/res/drawable-mdpi/ic_volume_bluetooth_ad2p.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_volume_bluetooth_in_call.png b/core/res/res/drawable-mdpi/ic_volume_bluetooth_in_call.png
index 94801fc..f1948ac 100644
--- a/core/res/res/drawable-mdpi/ic_volume_bluetooth_in_call.png
+++ b/core/res/res/drawable-mdpi/ic_volume_bluetooth_in_call.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_volume_off.png b/core/res/res/drawable-mdpi/ic_volume_off.png
index fefb9c4..ea00f81 100644
--- a/core/res/res/drawable-mdpi/ic_volume_off.png
+++ b/core/res/res/drawable-mdpi/ic_volume_off.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_volume_off_small.png b/core/res/res/drawable-mdpi/ic_volume_off_small.png
index 529298c..1ba0ca9 100644
--- a/core/res/res/drawable-mdpi/ic_volume_off_small.png
+++ b/core/res/res/drawable-mdpi/ic_volume_off_small.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_volume_small.png b/core/res/res/drawable-mdpi/ic_volume_small.png
index 2a7ec03..58912a8 100644
--- a/core/res/res/drawable-mdpi/ic_volume_small.png
+++ b/core/res/res/drawable-mdpi/ic_volume_small.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/icon_highlight_rectangle.9.png b/core/res/res/drawable-mdpi/icon_highlight_rectangle.9.png
index 3dafde3..7f3ed39 100644
--- a/core/res/res/drawable-mdpi/icon_highlight_rectangle.9.png
+++ b/core/res/res/drawable-mdpi/icon_highlight_rectangle.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/icon_highlight_square.9.png b/core/res/res/drawable-mdpi/icon_highlight_square.9.png
index a93a3f8..dbe38f6 100644
--- a/core/res/res/drawable-mdpi/icon_highlight_square.9.png
+++ b/core/res/res/drawable-mdpi/icon_highlight_square.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ime_qwerty.png b/core/res/res/drawable-mdpi/ime_qwerty.png
index e6e5cda..5db0050 100644
--- a/core/res/res/drawable-mdpi/ime_qwerty.png
+++ b/core/res/res/drawable-mdpi/ime_qwerty.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/indicator_input_error.png b/core/res/res/drawable-mdpi/indicator_input_error.png
index 775e417..0737bdd 100644
--- a/core/res/res/drawable-mdpi/indicator_input_error.png
+++ b/core/res/res/drawable-mdpi/indicator_input_error.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_dial_arrow_long_left_green.png b/core/res/res/drawable-mdpi/jog_dial_arrow_long_left_green.png
index 334a8e0..b9fb912 100644
--- a/core/res/res/drawable-mdpi/jog_dial_arrow_long_left_green.png
+++ b/core/res/res/drawable-mdpi/jog_dial_arrow_long_left_green.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_dial_arrow_long_left_yellow.png b/core/res/res/drawable-mdpi/jog_dial_arrow_long_left_yellow.png
index 2e011ca3..80a0115 100644
--- a/core/res/res/drawable-mdpi/jog_dial_arrow_long_left_yellow.png
+++ b/core/res/res/drawable-mdpi/jog_dial_arrow_long_left_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_dial_arrow_long_middle_yellow.png b/core/res/res/drawable-mdpi/jog_dial_arrow_long_middle_yellow.png
index 323745e..2192f0f 100644
--- a/core/res/res/drawable-mdpi/jog_dial_arrow_long_middle_yellow.png
+++ b/core/res/res/drawable-mdpi/jog_dial_arrow_long_middle_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_dial_arrow_long_right_red.png b/core/res/res/drawable-mdpi/jog_dial_arrow_long_right_red.png
index 1e97c9a..e5f02ad 100644
--- a/core/res/res/drawable-mdpi/jog_dial_arrow_long_right_red.png
+++ b/core/res/res/drawable-mdpi/jog_dial_arrow_long_right_red.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_dial_arrow_long_right_yellow.png b/core/res/res/drawable-mdpi/jog_dial_arrow_long_right_yellow.png
index 3536e58..4b14a3f 100644
--- a/core/res/res/drawable-mdpi/jog_dial_arrow_long_right_yellow.png
+++ b/core/res/res/drawable-mdpi/jog_dial_arrow_long_right_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_dial_arrow_short_left.png b/core/res/res/drawable-mdpi/jog_dial_arrow_short_left.png
index 4a4ab3ae..7420c1c 100644
--- a/core/res/res/drawable-mdpi/jog_dial_arrow_short_left.png
+++ b/core/res/res/drawable-mdpi/jog_dial_arrow_short_left.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_dial_arrow_short_left_and_right.png b/core/res/res/drawable-mdpi/jog_dial_arrow_short_left_and_right.png
index 987cfa7..bdc3ecc 100644
--- a/core/res/res/drawable-mdpi/jog_dial_arrow_short_left_and_right.png
+++ b/core/res/res/drawable-mdpi/jog_dial_arrow_short_left_and_right.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_dial_arrow_short_right.png b/core/res/res/drawable-mdpi/jog_dial_arrow_short_right.png
index ee79875..3d48be3 100644
--- a/core/res/res/drawable-mdpi/jog_dial_arrow_short_right.png
+++ b/core/res/res/drawable-mdpi/jog_dial_arrow_short_right.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_dial_bg.png b/core/res/res/drawable-mdpi/jog_dial_bg.png
index 2f8f24d..3397e01 100644
--- a/core/res/res/drawable-mdpi/jog_dial_bg.png
+++ b/core/res/res/drawable-mdpi/jog_dial_bg.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_dial_dimple.png b/core/res/res/drawable-mdpi/jog_dial_dimple.png
index 85d3a43..09cfb04 100644
--- a/core/res/res/drawable-mdpi/jog_dial_dimple.png
+++ b/core/res/res/drawable-mdpi/jog_dial_dimple.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_dial_dimple_dim.png b/core/res/res/drawable-mdpi/jog_dial_dimple_dim.png
index 664e89d..3852351 100644
--- a/core/res/res/drawable-mdpi/jog_dial_dimple_dim.png
+++ b/core/res/res/drawable-mdpi/jog_dial_dimple_dim.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_bar_left_end_confirm_gray.9.png b/core/res/res/drawable-mdpi/jog_tab_bar_left_end_confirm_gray.9.png
index 0f1190b..e1d9baa 100644
--- a/core/res/res/drawable-mdpi/jog_tab_bar_left_end_confirm_gray.9.png
+++ b/core/res/res/drawable-mdpi/jog_tab_bar_left_end_confirm_gray.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_bar_left_end_confirm_green.9.png b/core/res/res/drawable-mdpi/jog_tab_bar_left_end_confirm_green.9.png
index 88ca2e0..fbaff30 100644
--- a/core/res/res/drawable-mdpi/jog_tab_bar_left_end_confirm_green.9.png
+++ b/core/res/res/drawable-mdpi/jog_tab_bar_left_end_confirm_green.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_bar_left_end_confirm_red.9.png b/core/res/res/drawable-mdpi/jog_tab_bar_left_end_confirm_red.9.png
index f0f9436..0c875a3 100644
--- a/core/res/res/drawable-mdpi/jog_tab_bar_left_end_confirm_red.9.png
+++ b/core/res/res/drawable-mdpi/jog_tab_bar_left_end_confirm_red.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_bar_left_end_confirm_yellow.9.png b/core/res/res/drawable-mdpi/jog_tab_bar_left_end_confirm_yellow.9.png
index 8aa1263..ba4185c 100644
--- a/core/res/res/drawable-mdpi/jog_tab_bar_left_end_confirm_yellow.9.png
+++ b/core/res/res/drawable-mdpi/jog_tab_bar_left_end_confirm_yellow.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_bar_left_end_normal.9.png b/core/res/res/drawable-mdpi/jog_tab_bar_left_end_normal.9.png
index 4a89f4b..9929f0a 100644
--- a/core/res/res/drawable-mdpi/jog_tab_bar_left_end_normal.9.png
+++ b/core/res/res/drawable-mdpi/jog_tab_bar_left_end_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_bar_left_end_pressed.9.png b/core/res/res/drawable-mdpi/jog_tab_bar_left_end_pressed.9.png
index 78c7a9f..7e1f608 100644
--- a/core/res/res/drawable-mdpi/jog_tab_bar_left_end_pressed.9.png
+++ b/core/res/res/drawable-mdpi/jog_tab_bar_left_end_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_bar_right_end_confirm_gray.9.png b/core/res/res/drawable-mdpi/jog_tab_bar_right_end_confirm_gray.9.png
index a6ee329..cc83cb1 100644
--- a/core/res/res/drawable-mdpi/jog_tab_bar_right_end_confirm_gray.9.png
+++ b/core/res/res/drawable-mdpi/jog_tab_bar_right_end_confirm_gray.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_bar_right_end_confirm_green.9.png b/core/res/res/drawable-mdpi/jog_tab_bar_right_end_confirm_green.9.png
index 386ed9d..97e892a 100644
--- a/core/res/res/drawable-mdpi/jog_tab_bar_right_end_confirm_green.9.png
+++ b/core/res/res/drawable-mdpi/jog_tab_bar_right_end_confirm_green.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_bar_right_end_confirm_red.9.png b/core/res/res/drawable-mdpi/jog_tab_bar_right_end_confirm_red.9.png
index 0242a42..de1384b 100644
--- a/core/res/res/drawable-mdpi/jog_tab_bar_right_end_confirm_red.9.png
+++ b/core/res/res/drawable-mdpi/jog_tab_bar_right_end_confirm_red.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_bar_right_end_confirm_yellow.9.png b/core/res/res/drawable-mdpi/jog_tab_bar_right_end_confirm_yellow.9.png
index b8c2e18..3866d4a 100644
--- a/core/res/res/drawable-mdpi/jog_tab_bar_right_end_confirm_yellow.9.png
+++ b/core/res/res/drawable-mdpi/jog_tab_bar_right_end_confirm_yellow.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_bar_right_end_normal.9.png b/core/res/res/drawable-mdpi/jog_tab_bar_right_end_normal.9.png
index 36f9a32..34bf9bd 100644
--- a/core/res/res/drawable-mdpi/jog_tab_bar_right_end_normal.9.png
+++ b/core/res/res/drawable-mdpi/jog_tab_bar_right_end_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_bar_right_end_pressed.9.png b/core/res/res/drawable-mdpi/jog_tab_bar_right_end_pressed.9.png
index 8bdfd84..4f21164 100644
--- a/core/res/res/drawable-mdpi/jog_tab_bar_right_end_pressed.9.png
+++ b/core/res/res/drawable-mdpi/jog_tab_bar_right_end_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_left_confirm_gray.png b/core/res/res/drawable-mdpi/jog_tab_left_confirm_gray.png
index 3dce451..1b4ab22 100644
--- a/core/res/res/drawable-mdpi/jog_tab_left_confirm_gray.png
+++ b/core/res/res/drawable-mdpi/jog_tab_left_confirm_gray.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_left_confirm_green.png b/core/res/res/drawable-mdpi/jog_tab_left_confirm_green.png
index 829b146..e611de6 100644
--- a/core/res/res/drawable-mdpi/jog_tab_left_confirm_green.png
+++ b/core/res/res/drawable-mdpi/jog_tab_left_confirm_green.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_left_confirm_red.png b/core/res/res/drawable-mdpi/jog_tab_left_confirm_red.png
index f2ceb2e..29075d2 100644
--- a/core/res/res/drawable-mdpi/jog_tab_left_confirm_red.png
+++ b/core/res/res/drawable-mdpi/jog_tab_left_confirm_red.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_left_confirm_yellow.png b/core/res/res/drawable-mdpi/jog_tab_left_confirm_yellow.png
index 5a29262..ccc939e 100644
--- a/core/res/res/drawable-mdpi/jog_tab_left_confirm_yellow.png
+++ b/core/res/res/drawable-mdpi/jog_tab_left_confirm_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_left_normal.png b/core/res/res/drawable-mdpi/jog_tab_left_normal.png
index eb91e97..3ba5000 100644
--- a/core/res/res/drawable-mdpi/jog_tab_left_normal.png
+++ b/core/res/res/drawable-mdpi/jog_tab_left_normal.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_left_pressed.png b/core/res/res/drawable-mdpi/jog_tab_left_pressed.png
index 9951992..68e7249 100644
--- a/core/res/res/drawable-mdpi/jog_tab_left_pressed.png
+++ b/core/res/res/drawable-mdpi/jog_tab_left_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_right_confirm_gray.png b/core/res/res/drawable-mdpi/jog_tab_right_confirm_gray.png
index d446480..fe55a16 100644
--- a/core/res/res/drawable-mdpi/jog_tab_right_confirm_gray.png
+++ b/core/res/res/drawable-mdpi/jog_tab_right_confirm_gray.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_right_confirm_green.png b/core/res/res/drawable-mdpi/jog_tab_right_confirm_green.png
index 96d7acb..c8b85bf 100644
--- a/core/res/res/drawable-mdpi/jog_tab_right_confirm_green.png
+++ b/core/res/res/drawable-mdpi/jog_tab_right_confirm_green.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_right_confirm_red.png b/core/res/res/drawable-mdpi/jog_tab_right_confirm_red.png
index 2e1e105..b4ae448 100644
--- a/core/res/res/drawable-mdpi/jog_tab_right_confirm_red.png
+++ b/core/res/res/drawable-mdpi/jog_tab_right_confirm_red.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_right_confirm_yellow.png b/core/res/res/drawable-mdpi/jog_tab_right_confirm_yellow.png
index 8224c38..b506f22 100644
--- a/core/res/res/drawable-mdpi/jog_tab_right_confirm_yellow.png
+++ b/core/res/res/drawable-mdpi/jog_tab_right_confirm_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_right_normal.png b/core/res/res/drawable-mdpi/jog_tab_right_normal.png
index f2113f2..e91eae3 100644
--- a/core/res/res/drawable-mdpi/jog_tab_right_normal.png
+++ b/core/res/res/drawable-mdpi/jog_tab_right_normal.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_right_pressed.png b/core/res/res/drawable-mdpi/jog_tab_right_pressed.png
index 65cd51e..c50ff44 100644
--- a/core/res/res/drawable-mdpi/jog_tab_right_pressed.png
+++ b/core/res/res/drawable-mdpi/jog_tab_right_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_target_gray.png b/core/res/res/drawable-mdpi/jog_tab_target_gray.png
index a1e25e1..621f0bc 100644
--- a/core/res/res/drawable-mdpi/jog_tab_target_gray.png
+++ b/core/res/res/drawable-mdpi/jog_tab_target_gray.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_target_green.png b/core/res/res/drawable-mdpi/jog_tab_target_green.png
index d1377ee..7aa1204 100644
--- a/core/res/res/drawable-mdpi/jog_tab_target_green.png
+++ b/core/res/res/drawable-mdpi/jog_tab_target_green.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_target_red.png b/core/res/res/drawable-mdpi/jog_tab_target_red.png
index b840bc6..4a93e5f 100644
--- a/core/res/res/drawable-mdpi/jog_tab_target_red.png
+++ b/core/res/res/drawable-mdpi/jog_tab_target_red.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_target_yellow.png b/core/res/res/drawable-mdpi/jog_tab_target_yellow.png
index 58b2e62..a8f9ee2 100644
--- a/core/res/res/drawable-mdpi/jog_tab_target_yellow.png
+++ b/core/res/res/drawable-mdpi/jog_tab_target_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/keyboard_accessory_bg_landscape.9.png b/core/res/res/drawable-mdpi/keyboard_accessory_bg_landscape.9.png
index 8f828f6..c921a48 100644
--- a/core/res/res/drawable-mdpi/keyboard_accessory_bg_landscape.9.png
+++ b/core/res/res/drawable-mdpi/keyboard_accessory_bg_landscape.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/keyboard_background.9.png b/core/res/res/drawable-mdpi/keyboard_background.9.png
index 1d3ce05..0db893f 100644
--- a/core/res/res/drawable-mdpi/keyboard_background.9.png
+++ b/core/res/res/drawable-mdpi/keyboard_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/keyboard_key_feedback_background.9.png b/core/res/res/drawable-mdpi/keyboard_key_feedback_background.9.png
index 2a80f09..b205bb0 100644
--- a/core/res/res/drawable-mdpi/keyboard_key_feedback_background.9.png
+++ b/core/res/res/drawable-mdpi/keyboard_key_feedback_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/keyboard_key_feedback_more_background.9.png b/core/res/res/drawable-mdpi/keyboard_key_feedback_more_background.9.png
index 29aa285..08b6df4 100644
--- a/core/res/res/drawable-mdpi/keyboard_key_feedback_more_background.9.png
+++ b/core/res/res/drawable-mdpi/keyboard_key_feedback_more_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/keyboard_popup_panel_background.9.png b/core/res/res/drawable-mdpi/keyboard_popup_panel_background.9.png
index 36d75df..50cf4a3 100644
--- a/core/res/res/drawable-mdpi/keyboard_popup_panel_background.9.png
+++ b/core/res/res/drawable-mdpi/keyboard_popup_panel_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/keyboard_popup_panel_trans_background.9.png b/core/res/res/drawable-mdpi/keyboard_popup_panel_trans_background.9.png
index 4ba2a49..0b55d83 100644
--- a/core/res/res/drawable-mdpi/keyboard_popup_panel_trans_background.9.png
+++ b/core/res/res/drawable-mdpi/keyboard_popup_panel_trans_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/light_header.9.png b/core/res/res/drawable-mdpi/light_header.9.png
index fcd9e2d..767889b 100644
--- a/core/res/res/drawable-mdpi/light_header.9.png
+++ b/core/res/res/drawable-mdpi/light_header.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_activated_holo.9.png b/core/res/res/drawable-mdpi/list_activated_holo.9.png
index 3bf8e03..2f81bfa 100644
--- a/core/res/res/drawable-mdpi/list_activated_holo.9.png
+++ b/core/res/res/drawable-mdpi/list_activated_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_divider_holo_dark.9.png b/core/res/res/drawable-mdpi/list_divider_holo_dark.9.png
index 986ab0b..b78f409 100644
--- a/core/res/res/drawable-mdpi/list_divider_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/list_divider_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_divider_holo_light.9.png b/core/res/res/drawable-mdpi/list_divider_holo_light.9.png
index 0279e17..ab53898 100644
--- a/core/res/res/drawable-mdpi/list_divider_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/list_divider_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_divider_horizontal_holo_dark.9.png b/core/res/res/drawable-mdpi/list_divider_horizontal_holo_dark.9.png
index 0a4347f..cb477c2 100644
--- a/core/res/res/drawable-mdpi/list_divider_horizontal_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/list_divider_horizontal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_focused_holo.9.png b/core/res/res/drawable-mdpi/list_focused_holo.9.png
index 00f05d8..b5a6735 100644
--- a/core/res/res/drawable-mdpi/list_focused_holo.9.png
+++ b/core/res/res/drawable-mdpi/list_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_longpressed_holo.9.png b/core/res/res/drawable-mdpi/list_longpressed_holo.9.png
index 3bf8e03..2f81bfa 100644
--- a/core/res/res/drawable-mdpi/list_longpressed_holo.9.png
+++ b/core/res/res/drawable-mdpi/list_longpressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_longpressed_holo_dark.9.png b/core/res/res/drawable-mdpi/list_longpressed_holo_dark.9.png
index c6c1c02..2931018 100644
--- a/core/res/res/drawable-mdpi/list_longpressed_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/list_longpressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_longpressed_holo_light.9.png b/core/res/res/drawable-mdpi/list_longpressed_holo_light.9.png
index 3226ab7..44dcb9a 100644
--- a/core/res/res/drawable-mdpi/list_longpressed_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/list_longpressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/list_pressed_holo_dark.9.png
index fd0e8d7..e6d3f8f 100644
--- a/core/res/res/drawable-mdpi/list_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/list_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/list_pressed_holo_light.9.png
index 061904c..1521d16 100644
--- a/core/res/res/drawable-mdpi/list_pressed_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/list_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_section_divider_holo_dark.9.png b/core/res/res/drawable-mdpi/list_section_divider_holo_dark.9.png
index af0bc16..c25a32b 100644
--- a/core/res/res/drawable-mdpi/list_section_divider_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/list_section_divider_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_section_divider_holo_light.9.png b/core/res/res/drawable-mdpi/list_section_divider_holo_light.9.png
index c2f2dd8..db9d254 100644
--- a/core/res/res/drawable-mdpi/list_section_divider_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/list_section_divider_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_section_divider_mtrl_alpha.9.png b/core/res/res/drawable-mdpi/list_section_divider_mtrl_alpha.9.png
index 11ae4f4..c79e087 100644
--- a/core/res/res/drawable-mdpi/list_section_divider_mtrl_alpha.9.png
+++ b/core/res/res/drawable-mdpi/list_section_divider_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_section_header_holo_dark.9.png b/core/res/res/drawable-mdpi/list_section_header_holo_dark.9.png
index 48dfea0..51c3084 100644
--- a/core/res/res/drawable-mdpi/list_section_header_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/list_section_header_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_section_header_holo_light.9.png b/core/res/res/drawable-mdpi/list_section_header_holo_light.9.png
index 36a046b..781eb16 100644
--- a/core/res/res/drawable-mdpi/list_section_header_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/list_section_header_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selected_holo_dark.9.png b/core/res/res/drawable-mdpi/list_selected_holo_dark.9.png
index 5f97f2b..3211786 100644
--- a/core/res/res/drawable-mdpi/list_selected_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/list_selected_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selected_holo_light.9.png b/core/res/res/drawable-mdpi/list_selected_holo_light.9.png
index 779d10e..9131235 100644
--- a/core/res/res/drawable-mdpi/list_selected_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/list_selected_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_activated_holo_dark.9.png b/core/res/res/drawable-mdpi/list_selector_activated_holo_dark.9.png
index 66bc259..b4af0c8 100644
--- a/core/res/res/drawable-mdpi/list_selector_activated_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/list_selector_activated_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_activated_holo_light.9.png b/core/res/res/drawable-mdpi/list_selector_activated_holo_light.9.png
index c5822b1..03ce40a 100644
--- a/core/res/res/drawable-mdpi/list_selector_activated_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/list_selector_activated_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_background_default.9.png b/core/res/res/drawable-mdpi/list_selector_background_default.9.png
index cac71b0..a4b41cf 100644
--- a/core/res/res/drawable-mdpi/list_selector_background_default.9.png
+++ b/core/res/res/drawable-mdpi/list_selector_background_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_background_default_light.9.png b/core/res/res/drawable-mdpi/list_selector_background_default_light.9.png
index bdedffd..667d24d 100644
--- a/core/res/res/drawable-mdpi/list_selector_background_default_light.9.png
+++ b/core/res/res/drawable-mdpi/list_selector_background_default_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_background_disabled.9.png b/core/res/res/drawable-mdpi/list_selector_background_disabled.9.png
index 8ad0b32..dddc133 100644
--- a/core/res/res/drawable-mdpi/list_selector_background_disabled.9.png
+++ b/core/res/res/drawable-mdpi/list_selector_background_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_background_disabled_light.9.png b/core/res/res/drawable-mdpi/list_selector_background_disabled_light.9.png
index bc992612..eaafd06 100644
--- a/core/res/res/drawable-mdpi/list_selector_background_disabled_light.9.png
+++ b/core/res/res/drawable-mdpi/list_selector_background_disabled_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_background_focus.9.png b/core/res/res/drawable-mdpi/list_selector_background_focus.9.png
index da625af..268a011 100644
--- a/core/res/res/drawable-mdpi/list_selector_background_focus.9.png
+++ b/core/res/res/drawable-mdpi/list_selector_background_focus.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_background_focused.9.png b/core/res/res/drawable-mdpi/list_selector_background_focused.9.png
index 5b1f195..cf2a4d6 100644
--- a/core/res/res/drawable-mdpi/list_selector_background_focused.9.png
+++ b/core/res/res/drawable-mdpi/list_selector_background_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_background_focused_light.9.png b/core/res/res/drawable-mdpi/list_selector_background_focused_light.9.png
index 5b1f195..cf2a4d6 100644
--- a/core/res/res/drawable-mdpi/list_selector_background_focused_light.9.png
+++ b/core/res/res/drawable-mdpi/list_selector_background_focused_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_background_focused_selected.9.png b/core/res/res/drawable-mdpi/list_selector_background_focused_selected.9.png
index e5b0c1d..0d82858 100644
--- a/core/res/res/drawable-mdpi/list_selector_background_focused_selected.9.png
+++ b/core/res/res/drawable-mdpi/list_selector_background_focused_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_background_longpress.9.png b/core/res/res/drawable-mdpi/list_selector_background_longpress.9.png
index fbf7ef0..8fab9c9 100644
--- a/core/res/res/drawable-mdpi/list_selector_background_longpress.9.png
+++ b/core/res/res/drawable-mdpi/list_selector_background_longpress.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_background_longpress_light.9.png b/core/res/res/drawable-mdpi/list_selector_background_longpress_light.9.png
index 646fc69..92706f9 100644
--- a/core/res/res/drawable-mdpi/list_selector_background_longpress_light.9.png
+++ b/core/res/res/drawable-mdpi/list_selector_background_longpress_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_background_pressed.9.png b/core/res/res/drawable-mdpi/list_selector_background_pressed.9.png
index dd2a024..4a183f7 100644
--- a/core/res/res/drawable-mdpi/list_selector_background_pressed.9.png
+++ b/core/res/res/drawable-mdpi/list_selector_background_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_background_pressed_light.9.png b/core/res/res/drawable-mdpi/list_selector_background_pressed_light.9.png
index fdf6f49..1570be9 100644
--- a/core/res/res/drawable-mdpi/list_selector_background_pressed_light.9.png
+++ b/core/res/res/drawable-mdpi/list_selector_background_pressed_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_background_selected.9.png b/core/res/res/drawable-mdpi/list_selector_background_selected.9.png
index a4ac1e3..b67a400 100644
--- a/core/res/res/drawable-mdpi/list_selector_background_selected.9.png
+++ b/core/res/res/drawable-mdpi/list_selector_background_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_background_selected_light.9.png b/core/res/res/drawable-mdpi/list_selector_background_selected_light.9.png
index d086194..07dd054 100644
--- a/core/res/res/drawable-mdpi/list_selector_background_selected_light.9.png
+++ b/core/res/res/drawable-mdpi/list_selector_background_selected_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/list_selector_disabled_holo_dark.9.png
index 92da2f0..e362ad4 100644
--- a/core/res/res/drawable-mdpi/list_selector_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/list_selector_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_disabled_holo_light.9.png b/core/res/res/drawable-mdpi/list_selector_disabled_holo_light.9.png
index 42cb646..5bbd5ce 100644
--- a/core/res/res/drawable-mdpi/list_selector_disabled_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/list_selector_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/list_selector_focused_holo_dark.9.png
index eb4555d..2d0b114 100644
--- a/core/res/res/drawable-mdpi/list_selector_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/list_selector_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_focused_holo_light.9.png b/core/res/res/drawable-mdpi/list_selector_focused_holo_light.9.png
index d799fbf..899d264 100644
--- a/core/res/res/drawable-mdpi/list_selector_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/list_selector_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_multiselect_holo_dark.9.png b/core/res/res/drawable-mdpi/list_selector_multiselect_holo_dark.9.png
index 2c3647e..55b94271c 100644
--- a/core/res/res/drawable-mdpi/list_selector_multiselect_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/list_selector_multiselect_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_multiselect_holo_light.9.png b/core/res/res/drawable-mdpi/list_selector_multiselect_holo_light.9.png
index 860c58e..c204ff9 100644
--- a/core/res/res/drawable-mdpi/list_selector_multiselect_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/list_selector_multiselect_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/list_selector_pressed_holo_dark.9.png
index bf36a43..f4db1d2 100644
--- a/core/res/res/drawable-mdpi/list_selector_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/list_selector_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/list_selector_pressed_holo_light.9.png
index 0f0be2a..ab89e4c 100644
--- a/core/res/res/drawable-mdpi/list_selector_pressed_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/list_selector_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/magnified_region_frame.9.png b/core/res/res/drawable-mdpi/magnified_region_frame.9.png
index a61cbea..c7f5604 100644
--- a/core/res/res/drawable-mdpi/magnified_region_frame.9.png
+++ b/core/res/res/drawable-mdpi/magnified_region_frame.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/maps_google_logo.png b/core/res/res/drawable-mdpi/maps_google_logo.png
index 1374aaa..c38223d 100644
--- a/core/res/res/drawable-mdpi/maps_google_logo.png
+++ b/core/res/res/drawable-mdpi/maps_google_logo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/menu_background.9.png b/core/res/res/drawable-mdpi/menu_background.9.png
index 41a3d34..69ce25c 100644
--- a/core/res/res/drawable-mdpi/menu_background.9.png
+++ b/core/res/res/drawable-mdpi/menu_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/menu_background_fill_parent_width.9.png b/core/res/res/drawable-mdpi/menu_background_fill_parent_width.9.png
index 1ddf091..14fced4 100644
--- a/core/res/res/drawable-mdpi/menu_background_fill_parent_width.9.png
+++ b/core/res/res/drawable-mdpi/menu_background_fill_parent_width.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_dark.9.png b/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_dark.9.png
index 31dc342..a0cdeeb 100644
--- a/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_light.9.png b/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_light.9.png
index 755c145..74ee7d7 100644
--- a/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/menu_hardkey_panel_holo_dark.9.png b/core/res/res/drawable-mdpi/menu_hardkey_panel_holo_dark.9.png
index 3677994..d86ee4d 100644
--- a/core/res/res/drawable-mdpi/menu_hardkey_panel_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/menu_hardkey_panel_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/menu_hardkey_panel_holo_light.9.png b/core/res/res/drawable-mdpi/menu_hardkey_panel_holo_light.9.png
index 02b25f0..94cf93f 100644
--- a/core/res/res/drawable-mdpi/menu_hardkey_panel_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/menu_hardkey_panel_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/menu_popup_panel_holo_dark.9.png b/core/res/res/drawable-mdpi/menu_popup_panel_holo_dark.9.png
index 2020a42..f8ed411 100644
--- a/core/res/res/drawable-mdpi/menu_popup_panel_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/menu_popup_panel_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/menu_popup_panel_holo_light.9.png b/core/res/res/drawable-mdpi/menu_popup_panel_holo_light.9.png
index 7cae402..aeba6d3 100644
--- a/core/res/res/drawable-mdpi/menu_popup_panel_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/menu_popup_panel_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/menu_separator.9.png b/core/res/res/drawable-mdpi/menu_separator.9.png
index 8a1a336..2660afd 100644
--- a/core/res/res/drawable-mdpi/menu_separator.9.png
+++ b/core/res/res/drawable-mdpi/menu_separator.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/menu_submenu_background.9.png b/core/res/res/drawable-mdpi/menu_submenu_background.9.png
index 2281c46..6ea551f 100644
--- a/core/res/res/drawable-mdpi/menu_submenu_background.9.png
+++ b/core/res/res/drawable-mdpi/menu_submenu_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/menuitem_background_focus.9.png b/core/res/res/drawable-mdpi/menuitem_background_focus.9.png
index c3e24158..6416956 100644
--- a/core/res/res/drawable-mdpi/menuitem_background_focus.9.png
+++ b/core/res/res/drawable-mdpi/menuitem_background_focus.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/menuitem_background_pressed.9.png b/core/res/res/drawable-mdpi/menuitem_background_pressed.9.png
index 02b4e9a..cb4ea64 100644
--- a/core/res/res/drawable-mdpi/menuitem_background_pressed.9.png
+++ b/core/res/res/drawable-mdpi/menuitem_background_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/menuitem_background_solid_focused.9.png b/core/res/res/drawable-mdpi/menuitem_background_solid_focused.9.png
index 99dd9b1..533bda8 100644
--- a/core/res/res/drawable-mdpi/menuitem_background_solid_focused.9.png
+++ b/core/res/res/drawable-mdpi/menuitem_background_solid_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/menuitem_background_solid_pressed.9.png b/core/res/res/drawable-mdpi/menuitem_background_solid_pressed.9.png
index 389063a..233e108 100644
--- a/core/res/res/drawable-mdpi/menuitem_background_solid_pressed.9.png
+++ b/core/res/res/drawable-mdpi/menuitem_background_solid_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/menuitem_checkbox_on.png b/core/res/res/drawable-mdpi/menuitem_checkbox_on.png
index bd8ff93..762ea55 100644
--- a/core/res/res/drawable-mdpi/menuitem_checkbox_on.png
+++ b/core/res/res/drawable-mdpi/menuitem_checkbox_on.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/minitab_lt_focus.9.png b/core/res/res/drawable-mdpi/minitab_lt_focus.9.png
index 415c571..5d6eff3 100644
--- a/core/res/res/drawable-mdpi/minitab_lt_focus.9.png
+++ b/core/res/res/drawable-mdpi/minitab_lt_focus.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/minitab_lt_press.9.png b/core/res/res/drawable-mdpi/minitab_lt_press.9.png
index 4166543..cc2452c 100644
--- a/core/res/res/drawable-mdpi/minitab_lt_press.9.png
+++ b/core/res/res/drawable-mdpi/minitab_lt_press.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/minitab_lt_selected.9.png b/core/res/res/drawable-mdpi/minitab_lt_selected.9.png
index fefa27e..82085ea 100644
--- a/core/res/res/drawable-mdpi/minitab_lt_selected.9.png
+++ b/core/res/res/drawable-mdpi/minitab_lt_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/minitab_lt_unselected.9.png b/core/res/res/drawable-mdpi/minitab_lt_unselected.9.png
index 0051cd5..47b8530 100644
--- a/core/res/res/drawable-mdpi/minitab_lt_unselected.9.png
+++ b/core/res/res/drawable-mdpi/minitab_lt_unselected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/minitab_lt_unselected_press.9.png b/core/res/res/drawable-mdpi/minitab_lt_unselected_press.9.png
index 69444dd..3def8d8 100644
--- a/core/res/res/drawable-mdpi/minitab_lt_unselected_press.9.png
+++ b/core/res/res/drawable-mdpi/minitab_lt_unselected_press.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_down_disabled.9.png b/core/res/res/drawable-mdpi/numberpicker_down_disabled.9.png
index 596294b..f20dbf2 100644
--- a/core/res/res/drawable-mdpi/numberpicker_down_disabled.9.png
+++ b/core/res/res/drawable-mdpi/numberpicker_down_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_down_disabled_focused.9.png b/core/res/res/drawable-mdpi/numberpicker_down_disabled_focused.9.png
index 662cffd..aefc478 100644
--- a/core/res/res/drawable-mdpi/numberpicker_down_disabled_focused.9.png
+++ b/core/res/res/drawable-mdpi/numberpicker_down_disabled_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_down_normal.9.png b/core/res/res/drawable-mdpi/numberpicker_down_normal.9.png
index f17e8f9..4026bd4 100644
--- a/core/res/res/drawable-mdpi/numberpicker_down_normal.9.png
+++ b/core/res/res/drawable-mdpi/numberpicker_down_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_down_pressed.9.png b/core/res/res/drawable-mdpi/numberpicker_down_pressed.9.png
index 777bcf5..d407cd4 100644
--- a/core/res/res/drawable-mdpi/numberpicker_down_pressed.9.png
+++ b/core/res/res/drawable-mdpi/numberpicker_down_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_down_selected.9.png b/core/res/res/drawable-mdpi/numberpicker_down_selected.9.png
index b45db62..0e24924 100644
--- a/core/res/res/drawable-mdpi/numberpicker_down_selected.9.png
+++ b/core/res/res/drawable-mdpi/numberpicker_down_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_input_disabled.9.png b/core/res/res/drawable-mdpi/numberpicker_input_disabled.9.png
index f73658e..dcf4388 100644
--- a/core/res/res/drawable-mdpi/numberpicker_input_disabled.9.png
+++ b/core/res/res/drawable-mdpi/numberpicker_input_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_input_normal.9.png b/core/res/res/drawable-mdpi/numberpicker_input_normal.9.png
index 8032ada..7589d8d 100644
--- a/core/res/res/drawable-mdpi/numberpicker_input_normal.9.png
+++ b/core/res/res/drawable-mdpi/numberpicker_input_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_input_pressed.9.png b/core/res/res/drawable-mdpi/numberpicker_input_pressed.9.png
index 30d8d5f..64ec42f 100644
--- a/core/res/res/drawable-mdpi/numberpicker_input_pressed.9.png
+++ b/core/res/res/drawable-mdpi/numberpicker_input_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_input_selected.9.png b/core/res/res/drawable-mdpi/numberpicker_input_selected.9.png
index 874f18f..987cc7e 100644
--- a/core/res/res/drawable-mdpi/numberpicker_input_selected.9.png
+++ b/core/res/res/drawable-mdpi/numberpicker_input_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_selection_divider.9.png b/core/res/res/drawable-mdpi/numberpicker_selection_divider.9.png
index 076fc16..2ca26e4 100644
--- a/core/res/res/drawable-mdpi/numberpicker_selection_divider.9.png
+++ b/core/res/res/drawable-mdpi/numberpicker_selection_divider.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_up_disabled.9.png b/core/res/res/drawable-mdpi/numberpicker_up_disabled.9.png
index 327b0b5..3613d8e 100644
--- a/core/res/res/drawable-mdpi/numberpicker_up_disabled.9.png
+++ b/core/res/res/drawable-mdpi/numberpicker_up_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_up_disabled_focused.9.png b/core/res/res/drawable-mdpi/numberpicker_up_disabled_focused.9.png
index 4c96680..b5d4de3 100644
--- a/core/res/res/drawable-mdpi/numberpicker_up_disabled_focused.9.png
+++ b/core/res/res/drawable-mdpi/numberpicker_up_disabled_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_up_normal.9.png b/core/res/res/drawable-mdpi/numberpicker_up_normal.9.png
index dcd26e0..3c718d4 100644
--- a/core/res/res/drawable-mdpi/numberpicker_up_normal.9.png
+++ b/core/res/res/drawable-mdpi/numberpicker_up_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_up_pressed.9.png b/core/res/res/drawable-mdpi/numberpicker_up_pressed.9.png
index 7dac778..18f3045 100644
--- a/core/res/res/drawable-mdpi/numberpicker_up_pressed.9.png
+++ b/core/res/res/drawable-mdpi/numberpicker_up_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_up_selected.9.png b/core/res/res/drawable-mdpi/numberpicker_up_selected.9.png
index 35dae8ef..0d2dedd 100644
--- a/core/res/res/drawable-mdpi/numberpicker_up_selected.9.png
+++ b/core/res/res/drawable-mdpi/numberpicker_up_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/panel_background.9.png b/core/res/res/drawable-mdpi/panel_background.9.png
index 822b6c6..365ff08 100644
--- a/core/res/res/drawable-mdpi/panel_background.9.png
+++ b/core/res/res/drawable-mdpi/panel_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/panel_bg_holo_dark.9.png b/core/res/res/drawable-mdpi/panel_bg_holo_dark.9.png
index 588eb3c..b727e23 100644
--- a/core/res/res/drawable-mdpi/panel_bg_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/panel_bg_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/panel_bg_holo_light.9.png b/core/res/res/drawable-mdpi/panel_bg_holo_light.9.png
index c1cdbc7..6b4b923 100644
--- a/core/res/res/drawable-mdpi/panel_bg_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/panel_bg_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/panel_picture_frame_bg_focus_blue.9.png b/core/res/res/drawable-mdpi/panel_picture_frame_bg_focus_blue.9.png
index 7ebdbe5..8b238f0 100644
--- a/core/res/res/drawable-mdpi/panel_picture_frame_bg_focus_blue.9.png
+++ b/core/res/res/drawable-mdpi/panel_picture_frame_bg_focus_blue.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/panel_picture_frame_bg_normal.9.png b/core/res/res/drawable-mdpi/panel_picture_frame_bg_normal.9.png
index fd17d09..9162424 100644
--- a/core/res/res/drawable-mdpi/panel_picture_frame_bg_normal.9.png
+++ b/core/res/res/drawable-mdpi/panel_picture_frame_bg_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/panel_picture_frame_bg_pressed_blue.9.png b/core/res/res/drawable-mdpi/panel_picture_frame_bg_pressed_blue.9.png
index 7bb0216..7520831 100644
--- a/core/res/res/drawable-mdpi/panel_picture_frame_bg_pressed_blue.9.png
+++ b/core/res/res/drawable-mdpi/panel_picture_frame_bg_pressed_blue.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/password_field_default.9.png b/core/res/res/drawable-mdpi/password_field_default.9.png
index 3193275..11a85e5 100644
--- a/core/res/res/drawable-mdpi/password_field_default.9.png
+++ b/core/res/res/drawable-mdpi/password_field_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/password_keyboard_background_holo.9.png b/core/res/res/drawable-mdpi/password_keyboard_background_holo.9.png
index c56c704..1cdbfb3 100644
--- a/core/res/res/drawable-mdpi/password_keyboard_background_holo.9.png
+++ b/core/res/res/drawable-mdpi/password_keyboard_background_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_accessibility_features.png b/core/res/res/drawable-mdpi/perm_group_accessibility_features.png
index 57c4167..97f280f 100644
--- a/core/res/res/drawable-mdpi/perm_group_accessibility_features.png
+++ b/core/res/res/drawable-mdpi/perm_group_accessibility_features.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_affects_battery.png b/core/res/res/drawable-mdpi/perm_group_affects_battery.png
index 55a0b79..d1214d7 100644
--- a/core/res/res/drawable-mdpi/perm_group_affects_battery.png
+++ b/core/res/res/drawable-mdpi/perm_group_affects_battery.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_app_info.png b/core/res/res/drawable-mdpi/perm_group_app_info.png
index 8393586..1360fb3 100644
--- a/core/res/res/drawable-mdpi/perm_group_app_info.png
+++ b/core/res/res/drawable-mdpi/perm_group_app_info.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_audio_settings.png b/core/res/res/drawable-mdpi/perm_group_audio_settings.png
index 734429f..93547c9 100644
--- a/core/res/res/drawable-mdpi/perm_group_audio_settings.png
+++ b/core/res/res/drawable-mdpi/perm_group_audio_settings.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_bluetooth.png b/core/res/res/drawable-mdpi/perm_group_bluetooth.png
index 4b79c1a..1d03166 100644
--- a/core/res/res/drawable-mdpi/perm_group_bluetooth.png
+++ b/core/res/res/drawable-mdpi/perm_group_bluetooth.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_bookmarks.png b/core/res/res/drawable-mdpi/perm_group_bookmarks.png
index ca3d453..154b0b1 100644
--- a/core/res/res/drawable-mdpi/perm_group_bookmarks.png
+++ b/core/res/res/drawable-mdpi/perm_group_bookmarks.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_device_alarms.png b/core/res/res/drawable-mdpi/perm_group_device_alarms.png
index 48339cd..99defbc 100644
--- a/core/res/res/drawable-mdpi/perm_group_device_alarms.png
+++ b/core/res/res/drawable-mdpi/perm_group_device_alarms.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_display.png b/core/res/res/drawable-mdpi/perm_group_display.png
index 9738f15..b398885 100644
--- a/core/res/res/drawable-mdpi/perm_group_display.png
+++ b/core/res/res/drawable-mdpi/perm_group_display.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_network.png b/core/res/res/drawable-mdpi/perm_group_network.png
index c575d70..207c831 100644
--- a/core/res/res/drawable-mdpi/perm_group_network.png
+++ b/core/res/res/drawable-mdpi/perm_group_network.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_personal_info.png b/core/res/res/drawable-mdpi/perm_group_personal_info.png
index 13ec27e..f5533d8 100644
--- a/core/res/res/drawable-mdpi/perm_group_personal_info.png
+++ b/core/res/res/drawable-mdpi/perm_group_personal_info.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_screenlock.png b/core/res/res/drawable-mdpi/perm_group_screenlock.png
index 9d9bb75..a760c0b 100644
--- a/core/res/res/drawable-mdpi/perm_group_screenlock.png
+++ b/core/res/res/drawable-mdpi/perm_group_screenlock.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_shortrange_network.png b/core/res/res/drawable-mdpi/perm_group_shortrange_network.png
index 5d35676..f23ec2f 100644
--- a/core/res/res/drawable-mdpi/perm_group_shortrange_network.png
+++ b/core/res/res/drawable-mdpi/perm_group_shortrange_network.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_status_bar.png b/core/res/res/drawable-mdpi/perm_group_status_bar.png
index f10536b..61cff33 100644
--- a/core/res/res/drawable-mdpi/perm_group_status_bar.png
+++ b/core/res/res/drawable-mdpi/perm_group_status_bar.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_sync_settings.png b/core/res/res/drawable-mdpi/perm_group_sync_settings.png
index f5ef82b..3876955 100644
--- a/core/res/res/drawable-mdpi/perm_group_sync_settings.png
+++ b/core/res/res/drawable-mdpi/perm_group_sync_settings.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_system_clock.png b/core/res/res/drawable-mdpi/perm_group_system_clock.png
index 3a67642..ce402eb 100644
--- a/core/res/res/drawable-mdpi/perm_group_system_clock.png
+++ b/core/res/res/drawable-mdpi/perm_group_system_clock.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_system_tools.png b/core/res/res/drawable-mdpi/perm_group_system_tools.png
index fd282e6..012a3dd 100644
--- a/core/res/res/drawable-mdpi/perm_group_system_tools.png
+++ b/core/res/res/drawable-mdpi/perm_group_system_tools.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_voicemail.png b/core/res/res/drawable-mdpi/perm_group_voicemail.png
index 108a725..4e6fe7b 100644
--- a/core/res/res/drawable-mdpi/perm_group_voicemail.png
+++ b/core/res/res/drawable-mdpi/perm_group_voicemail.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_wallpaper.png b/core/res/res/drawable-mdpi/perm_group_wallpaper.png
index aa06f38..befa7ce 100644
--- a/core/res/res/drawable-mdpi/perm_group_wallpaper.png
+++ b/core/res/res/drawable-mdpi/perm_group_wallpaper.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/picture_emergency.png b/core/res/res/drawable-mdpi/picture_emergency.png
index a224b80..3e79079 100644
--- a/core/res/res/drawable-mdpi/picture_emergency.png
+++ b/core/res/res/drawable-mdpi/picture_emergency.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/picture_frame.9.png b/core/res/res/drawable-mdpi/picture_frame.9.png
index ba71570..7c053ec 100644
--- a/core/res/res/drawable-mdpi/picture_frame.9.png
+++ b/core/res/res/drawable-mdpi/picture_frame.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_alias_large.png b/core/res/res/drawable-mdpi/pointer_alias_large.png
index 283bf7f..606774d 100644
--- a/core/res/res/drawable-mdpi/pointer_alias_large.png
+++ b/core/res/res/drawable-mdpi/pointer_alias_large.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_arrow.png b/core/res/res/drawable-mdpi/pointer_arrow.png
index 0745db2..7a74ec1 100644
--- a/core/res/res/drawable-mdpi/pointer_arrow.png
+++ b/core/res/res/drawable-mdpi/pointer_arrow.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_copy.png b/core/res/res/drawable-mdpi/pointer_copy.png
index 7d41036..254485c 100644
--- a/core/res/res/drawable-mdpi/pointer_copy.png
+++ b/core/res/res/drawable-mdpi/pointer_copy.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_copy_large.png b/core/res/res/drawable-mdpi/pointer_copy_large.png
index 18f4696..2f0e082 100644
--- a/core/res/res/drawable-mdpi/pointer_copy_large.png
+++ b/core/res/res/drawable-mdpi/pointer_copy_large.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_crosshair_large.png b/core/res/res/drawable-mdpi/pointer_crosshair_large.png
index ea1f5fc..51faf96 100644
--- a/core/res/res/drawable-mdpi/pointer_crosshair_large.png
+++ b/core/res/res/drawable-mdpi/pointer_crosshair_large.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_grab_large.png b/core/res/res/drawable-mdpi/pointer_grab_large.png
index 2e32766..44a171c 100644
--- a/core/res/res/drawable-mdpi/pointer_grab_large.png
+++ b/core/res/res/drawable-mdpi/pointer_grab_large.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_grabbing_large.png b/core/res/res/drawable-mdpi/pointer_grabbing_large.png
index 3c54751..b602d2f 100644
--- a/core/res/res/drawable-mdpi/pointer_grabbing_large.png
+++ b/core/res/res/drawable-mdpi/pointer_grabbing_large.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_hand_large.png b/core/res/res/drawable-mdpi/pointer_hand_large.png
index 785047f..464ec28 100644
--- a/core/res/res/drawable-mdpi/pointer_hand_large.png
+++ b/core/res/res/drawable-mdpi/pointer_hand_large.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_help_large.png b/core/res/res/drawable-mdpi/pointer_help_large.png
index 6552f9bb..69d1e41 100644
--- a/core/res/res/drawable-mdpi/pointer_help_large.png
+++ b/core/res/res/drawable-mdpi/pointer_help_large.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_nodrop.png b/core/res/res/drawable-mdpi/pointer_nodrop.png
index ad13c66..aa92895 100644
--- a/core/res/res/drawable-mdpi/pointer_nodrop.png
+++ b/core/res/res/drawable-mdpi/pointer_nodrop.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_nodrop_large.png b/core/res/res/drawable-mdpi/pointer_nodrop_large.png
index da981df..e150d04 100644
--- a/core/res/res/drawable-mdpi/pointer_nodrop_large.png
+++ b/core/res/res/drawable-mdpi/pointer_nodrop_large.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_spot_anchor.png b/core/res/res/drawable-mdpi/pointer_spot_anchor.png
index 4e282e7..48d638b 100644
--- a/core/res/res/drawable-mdpi/pointer_spot_anchor.png
+++ b/core/res/res/drawable-mdpi/pointer_spot_anchor.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_spot_hover.png b/core/res/res/drawable-mdpi/pointer_spot_hover.png
index 67d0b06..b304815 100644
--- a/core/res/res/drawable-mdpi/pointer_spot_hover.png
+++ b/core/res/res/drawable-mdpi/pointer_spot_hover.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_spot_touch.png b/core/res/res/drawable-mdpi/pointer_spot_touch.png
index 45dc5c08..659f809 100644
--- a/core/res/res/drawable-mdpi/pointer_spot_touch.png
+++ b/core/res/res/drawable-mdpi/pointer_spot_touch.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_0.png b/core/res/res/drawable-mdpi/pointer_wait_0.png
index adb7806..ae32a44 100644
--- a/core/res/res/drawable-mdpi/pointer_wait_0.png
+++ b/core/res/res/drawable-mdpi/pointer_wait_0.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_1.png b/core/res/res/drawable-mdpi/pointer_wait_1.png
index fc6b42f..afadc31 100644
--- a/core/res/res/drawable-mdpi/pointer_wait_1.png
+++ b/core/res/res/drawable-mdpi/pointer_wait_1.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_10.png b/core/res/res/drawable-mdpi/pointer_wait_10.png
index 02968b5..4e5f3b0 100644
--- a/core/res/res/drawable-mdpi/pointer_wait_10.png
+++ b/core/res/res/drawable-mdpi/pointer_wait_10.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_11.png b/core/res/res/drawable-mdpi/pointer_wait_11.png
index 24f866b..f895e53 100644
--- a/core/res/res/drawable-mdpi/pointer_wait_11.png
+++ b/core/res/res/drawable-mdpi/pointer_wait_11.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_12.png b/core/res/res/drawable-mdpi/pointer_wait_12.png
index d1a31bc..7a155f5 100644
--- a/core/res/res/drawable-mdpi/pointer_wait_12.png
+++ b/core/res/res/drawable-mdpi/pointer_wait_12.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_13.png b/core/res/res/drawable-mdpi/pointer_wait_13.png
index b0c6798..a9ae639 100644
--- a/core/res/res/drawable-mdpi/pointer_wait_13.png
+++ b/core/res/res/drawable-mdpi/pointer_wait_13.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_14.png b/core/res/res/drawable-mdpi/pointer_wait_14.png
index 721e86d..6761dda 100644
--- a/core/res/res/drawable-mdpi/pointer_wait_14.png
+++ b/core/res/res/drawable-mdpi/pointer_wait_14.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_15.png b/core/res/res/drawable-mdpi/pointer_wait_15.png
index adb0199..98821ed 100644
--- a/core/res/res/drawable-mdpi/pointer_wait_15.png
+++ b/core/res/res/drawable-mdpi/pointer_wait_15.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_16.png b/core/res/res/drawable-mdpi/pointer_wait_16.png
index 3695c18..72f3853 100644
--- a/core/res/res/drawable-mdpi/pointer_wait_16.png
+++ b/core/res/res/drawable-mdpi/pointer_wait_16.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_17.png b/core/res/res/drawable-mdpi/pointer_wait_17.png
index 861605e..a7452ed 100644
--- a/core/res/res/drawable-mdpi/pointer_wait_17.png
+++ b/core/res/res/drawable-mdpi/pointer_wait_17.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_18.png b/core/res/res/drawable-mdpi/pointer_wait_18.png
index f5dfdcf..ecb4f72 100644
--- a/core/res/res/drawable-mdpi/pointer_wait_18.png
+++ b/core/res/res/drawable-mdpi/pointer_wait_18.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_19.png b/core/res/res/drawable-mdpi/pointer_wait_19.png
index 9d51f79..1ce5d70 100644
--- a/core/res/res/drawable-mdpi/pointer_wait_19.png
+++ b/core/res/res/drawable-mdpi/pointer_wait_19.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_2.png b/core/res/res/drawable-mdpi/pointer_wait_2.png
index d73a154..d42278a 100644
--- a/core/res/res/drawable-mdpi/pointer_wait_2.png
+++ b/core/res/res/drawable-mdpi/pointer_wait_2.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_20.png b/core/res/res/drawable-mdpi/pointer_wait_20.png
index 81d1d51..2736fea 100644
--- a/core/res/res/drawable-mdpi/pointer_wait_20.png
+++ b/core/res/res/drawable-mdpi/pointer_wait_20.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_21.png b/core/res/res/drawable-mdpi/pointer_wait_21.png
index 331820b..e2fafd1 100644
--- a/core/res/res/drawable-mdpi/pointer_wait_21.png
+++ b/core/res/res/drawable-mdpi/pointer_wait_21.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_22.png b/core/res/res/drawable-mdpi/pointer_wait_22.png
index 2678d32..24bd01a 100644
--- a/core/res/res/drawable-mdpi/pointer_wait_22.png
+++ b/core/res/res/drawable-mdpi/pointer_wait_22.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_23.png b/core/res/res/drawable-mdpi/pointer_wait_23.png
index d54d9eb..26c6129 100644
--- a/core/res/res/drawable-mdpi/pointer_wait_23.png
+++ b/core/res/res/drawable-mdpi/pointer_wait_23.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_24.png b/core/res/res/drawable-mdpi/pointer_wait_24.png
index 442ace7..2597963 100644
--- a/core/res/res/drawable-mdpi/pointer_wait_24.png
+++ b/core/res/res/drawable-mdpi/pointer_wait_24.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_25.png b/core/res/res/drawable-mdpi/pointer_wait_25.png
index 27ce60d..c925d82 100644
--- a/core/res/res/drawable-mdpi/pointer_wait_25.png
+++ b/core/res/res/drawable-mdpi/pointer_wait_25.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_26.png b/core/res/res/drawable-mdpi/pointer_wait_26.png
index 8143634..7c3735d 100644
--- a/core/res/res/drawable-mdpi/pointer_wait_26.png
+++ b/core/res/res/drawable-mdpi/pointer_wait_26.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_27.png b/core/res/res/drawable-mdpi/pointer_wait_27.png
index 496ab9a..d4f2f65 100644
--- a/core/res/res/drawable-mdpi/pointer_wait_27.png
+++ b/core/res/res/drawable-mdpi/pointer_wait_27.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_28.png b/core/res/res/drawable-mdpi/pointer_wait_28.png
index a2aab2b..582c276 100644
--- a/core/res/res/drawable-mdpi/pointer_wait_28.png
+++ b/core/res/res/drawable-mdpi/pointer_wait_28.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_29.png b/core/res/res/drawable-mdpi/pointer_wait_29.png
index 646d153..f79f715 100644
--- a/core/res/res/drawable-mdpi/pointer_wait_29.png
+++ b/core/res/res/drawable-mdpi/pointer_wait_29.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_3.png b/core/res/res/drawable-mdpi/pointer_wait_3.png
index 9f45afe..efc766e 100644
--- a/core/res/res/drawable-mdpi/pointer_wait_3.png
+++ b/core/res/res/drawable-mdpi/pointer_wait_3.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_30.png b/core/res/res/drawable-mdpi/pointer_wait_30.png
index 27b3fc4..636d793 100644
--- a/core/res/res/drawable-mdpi/pointer_wait_30.png
+++ b/core/res/res/drawable-mdpi/pointer_wait_30.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_31.png b/core/res/res/drawable-mdpi/pointer_wait_31.png
index 6dbe184..8f41a53 100644
--- a/core/res/res/drawable-mdpi/pointer_wait_31.png
+++ b/core/res/res/drawable-mdpi/pointer_wait_31.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_32.png b/core/res/res/drawable-mdpi/pointer_wait_32.png
index 9f072ef..deef9b7 100644
--- a/core/res/res/drawable-mdpi/pointer_wait_32.png
+++ b/core/res/res/drawable-mdpi/pointer_wait_32.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_33.png b/core/res/res/drawable-mdpi/pointer_wait_33.png
index 881ec5f..6cad76b 100644
--- a/core/res/res/drawable-mdpi/pointer_wait_33.png
+++ b/core/res/res/drawable-mdpi/pointer_wait_33.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_34.png b/core/res/res/drawable-mdpi/pointer_wait_34.png
index 94961e3..4b25825 100644
--- a/core/res/res/drawable-mdpi/pointer_wait_34.png
+++ b/core/res/res/drawable-mdpi/pointer_wait_34.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_35.png b/core/res/res/drawable-mdpi/pointer_wait_35.png
index dfa65d7..ccfaf74 100644
--- a/core/res/res/drawable-mdpi/pointer_wait_35.png
+++ b/core/res/res/drawable-mdpi/pointer_wait_35.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_4.png b/core/res/res/drawable-mdpi/pointer_wait_4.png
index 5d3d652..d39d13a 100644
--- a/core/res/res/drawable-mdpi/pointer_wait_4.png
+++ b/core/res/res/drawable-mdpi/pointer_wait_4.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_5.png b/core/res/res/drawable-mdpi/pointer_wait_5.png
index d440a82..1c5a7de 100644
--- a/core/res/res/drawable-mdpi/pointer_wait_5.png
+++ b/core/res/res/drawable-mdpi/pointer_wait_5.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_6.png b/core/res/res/drawable-mdpi/pointer_wait_6.png
index ae65590..5113b27 100644
--- a/core/res/res/drawable-mdpi/pointer_wait_6.png
+++ b/core/res/res/drawable-mdpi/pointer_wait_6.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_7.png b/core/res/res/drawable-mdpi/pointer_wait_7.png
index cd84aa5..766a716 100644
--- a/core/res/res/drawable-mdpi/pointer_wait_7.png
+++ b/core/res/res/drawable-mdpi/pointer_wait_7.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_8.png b/core/res/res/drawable-mdpi/pointer_wait_8.png
index 0b81a9a..80fb2d9 100644
--- a/core/res/res/drawable-mdpi/pointer_wait_8.png
+++ b/core/res/res/drawable-mdpi/pointer_wait_8.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_wait_9.png b/core/res/res/drawable-mdpi/pointer_wait_9.png
index c13a90c1..db07e87 100644
--- a/core/res/res/drawable-mdpi/pointer_wait_9.png
+++ b/core/res/res/drawable-mdpi/pointer_wait_9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_zoom_in_large.png b/core/res/res/drawable-mdpi/pointer_zoom_in_large.png
index 923ad79..9b0fa7f 100644
--- a/core/res/res/drawable-mdpi/pointer_zoom_in_large.png
+++ b/core/res/res/drawable-mdpi/pointer_zoom_in_large.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_zoom_out_large.png b/core/res/res/drawable-mdpi/pointer_zoom_out_large.png
index aa47eb9..1a9ec86 100644
--- a/core/res/res/drawable-mdpi/pointer_zoom_out_large.png
+++ b/core/res/res/drawable-mdpi/pointer_zoom_out_large.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/popup_background_mtrl_mult.9.png b/core/res/res/drawable-mdpi/popup_background_mtrl_mult.9.png
index e920499..708b053 100644
--- a/core/res/res/drawable-mdpi/popup_background_mtrl_mult.9.png
+++ b/core/res/res/drawable-mdpi/popup_background_mtrl_mult.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/popup_bottom_bright.9.png b/core/res/res/drawable-mdpi/popup_bottom_bright.9.png
index e7b713d..6b3e26b 100644
--- a/core/res/res/drawable-mdpi/popup_bottom_bright.9.png
+++ b/core/res/res/drawable-mdpi/popup_bottom_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/popup_bottom_dark.9.png b/core/res/res/drawable-mdpi/popup_bottom_dark.9.png
index 88ce336..36dc799 100644
--- a/core/res/res/drawable-mdpi/popup_bottom_dark.9.png
+++ b/core/res/res/drawable-mdpi/popup_bottom_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/popup_bottom_medium.9.png b/core/res/res/drawable-mdpi/popup_bottom_medium.9.png
index e5aaad0..1756047 100644
--- a/core/res/res/drawable-mdpi/popup_bottom_medium.9.png
+++ b/core/res/res/drawable-mdpi/popup_bottom_medium.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/popup_center_bright.9.png b/core/res/res/drawable-mdpi/popup_center_bright.9.png
index a259356..e0c87e6 100644
--- a/core/res/res/drawable-mdpi/popup_center_bright.9.png
+++ b/core/res/res/drawable-mdpi/popup_center_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/popup_center_dark.9.png b/core/res/res/drawable-mdpi/popup_center_dark.9.png
index 9378dbf..cd9b745 100644
--- a/core/res/res/drawable-mdpi/popup_center_dark.9.png
+++ b/core/res/res/drawable-mdpi/popup_center_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/popup_center_medium.9.png b/core/res/res/drawable-mdpi/popup_center_medium.9.png
index 885403c..6b74aaf 100644
--- a/core/res/res/drawable-mdpi/popup_center_medium.9.png
+++ b/core/res/res/drawable-mdpi/popup_center_medium.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/popup_full_bright.9.png b/core/res/res/drawable-mdpi/popup_full_bright.9.png
index d7fb3db..43f40e5 100644
--- a/core/res/res/drawable-mdpi/popup_full_bright.9.png
+++ b/core/res/res/drawable-mdpi/popup_full_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/popup_full_dark.9.png b/core/res/res/drawable-mdpi/popup_full_dark.9.png
index 7b9f291..c6ce46a 100644
--- a/core/res/res/drawable-mdpi/popup_full_dark.9.png
+++ b/core/res/res/drawable-mdpi/popup_full_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/popup_inline_error_above_am.9.png b/core/res/res/drawable-mdpi/popup_inline_error_above_am.9.png
index 1d93817..083f38c 100644
--- a/core/res/res/drawable-mdpi/popup_inline_error_above_am.9.png
+++ b/core/res/res/drawable-mdpi/popup_inline_error_above_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/popup_inline_error_above_holo_dark_am.9.png b/core/res/res/drawable-mdpi/popup_inline_error_above_holo_dark_am.9.png
index 19b153b..8ef953a 100644
--- a/core/res/res/drawable-mdpi/popup_inline_error_above_holo_dark_am.9.png
+++ b/core/res/res/drawable-mdpi/popup_inline_error_above_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/popup_inline_error_above_holo_light_am.9.png b/core/res/res/drawable-mdpi/popup_inline_error_above_holo_light_am.9.png
index c03e658..5011eb6 100644
--- a/core/res/res/drawable-mdpi/popup_inline_error_above_holo_light_am.9.png
+++ b/core/res/res/drawable-mdpi/popup_inline_error_above_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/popup_inline_error_am.9.png b/core/res/res/drawable-mdpi/popup_inline_error_am.9.png
index 17fbe4a..700314b0a 100644
--- a/core/res/res/drawable-mdpi/popup_inline_error_am.9.png
+++ b/core/res/res/drawable-mdpi/popup_inline_error_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/popup_inline_error_holo_dark_am.9.png b/core/res/res/drawable-mdpi/popup_inline_error_holo_dark_am.9.png
index c3b8db9..c0fc2ce 100644
--- a/core/res/res/drawable-mdpi/popup_inline_error_holo_dark_am.9.png
+++ b/core/res/res/drawable-mdpi/popup_inline_error_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/popup_inline_error_holo_light_am.9.png b/core/res/res/drawable-mdpi/popup_inline_error_holo_light_am.9.png
index c228a83..59898b9 100644
--- a/core/res/res/drawable-mdpi/popup_inline_error_holo_light_am.9.png
+++ b/core/res/res/drawable-mdpi/popup_inline_error_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/popup_top_bright.9.png b/core/res/res/drawable-mdpi/popup_top_bright.9.png
index 72d82f0..94d69df 100644
--- a/core/res/res/drawable-mdpi/popup_top_bright.9.png
+++ b/core/res/res/drawable-mdpi/popup_top_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/popup_top_dark.9.png b/core/res/res/drawable-mdpi/popup_top_dark.9.png
index 616d80f..7ff19d4 100644
--- a/core/res/res/drawable-mdpi/popup_top_dark.9.png
+++ b/core/res/res/drawable-mdpi/popup_top_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_audio_away.png b/core/res/res/drawable-mdpi/presence_audio_away.png
index e68bc11..306c5c2 100644
--- a/core/res/res/drawable-mdpi/presence_audio_away.png
+++ b/core/res/res/drawable-mdpi/presence_audio_away.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_audio_busy.png b/core/res/res/drawable-mdpi/presence_audio_busy.png
index caa6d06..cf514b8 100644
--- a/core/res/res/drawable-mdpi/presence_audio_busy.png
+++ b/core/res/res/drawable-mdpi/presence_audio_busy.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_audio_online.png b/core/res/res/drawable-mdpi/presence_audio_online.png
index a740598..25b4700 100644
--- a/core/res/res/drawable-mdpi/presence_audio_online.png
+++ b/core/res/res/drawable-mdpi/presence_audio_online.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_away.png b/core/res/res/drawable-mdpi/presence_away.png
index 62ee0ca..023db51 100644
--- a/core/res/res/drawable-mdpi/presence_away.png
+++ b/core/res/res/drawable-mdpi/presence_away.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_busy.png b/core/res/res/drawable-mdpi/presence_busy.png
index 6def876..ca5fabe 100644
--- a/core/res/res/drawable-mdpi/presence_busy.png
+++ b/core/res/res/drawable-mdpi/presence_busy.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_invisible.png b/core/res/res/drawable-mdpi/presence_invisible.png
index 715a164..3ac36d0 100644
--- a/core/res/res/drawable-mdpi/presence_invisible.png
+++ b/core/res/res/drawable-mdpi/presence_invisible.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_offline.png b/core/res/res/drawable-mdpi/presence_offline.png
index 262d530..e8f13eb 100644
--- a/core/res/res/drawable-mdpi/presence_offline.png
+++ b/core/res/res/drawable-mdpi/presence_offline.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_online.png b/core/res/res/drawable-mdpi/presence_online.png
index e16ec81..d707462 100644
--- a/core/res/res/drawable-mdpi/presence_online.png
+++ b/core/res/res/drawable-mdpi/presence_online.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_video_away.png b/core/res/res/drawable-mdpi/presence_video_away.png
index 2d3508d..ff832c1 100644
--- a/core/res/res/drawable-mdpi/presence_video_away.png
+++ b/core/res/res/drawable-mdpi/presence_video_away.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_video_busy.png b/core/res/res/drawable-mdpi/presence_video_busy.png
index f317efa..c8dfecc 100644
--- a/core/res/res/drawable-mdpi/presence_video_busy.png
+++ b/core/res/res/drawable-mdpi/presence_video_busy.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_video_online.png b/core/res/res/drawable-mdpi/presence_video_online.png
index 777b6ff..86908d6 100644
--- a/core/res/res/drawable-mdpi/presence_video_online.png
+++ b/core/res/res/drawable-mdpi/presence_video_online.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pressed_application_background_static.png b/core/res/res/drawable-mdpi/pressed_application_background_static.png
index 070f6fd..a71d552 100644
--- a/core/res/res/drawable-mdpi/pressed_application_background_static.png
+++ b/core/res/res/drawable-mdpi/pressed_application_background_static.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progress_bg_holo_dark.9.png b/core/res/res/drawable-mdpi/progress_bg_holo_dark.9.png
index b1f5cf3..7e26f07 100644
--- a/core/res/res/drawable-mdpi/progress_bg_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/progress_bg_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progress_bg_holo_light.9.png b/core/res/res/drawable-mdpi/progress_bg_holo_light.9.png
index 780b4b2..f84884c 100644
--- a/core/res/res/drawable-mdpi/progress_bg_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/progress_bg_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progress_primary_holo_dark.9.png b/core/res/res/drawable-mdpi/progress_primary_holo_dark.9.png
index b86f4b5..fc0e191 100644
--- a/core/res/res/drawable-mdpi/progress_primary_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/progress_primary_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progress_primary_holo_light.9.png b/core/res/res/drawable-mdpi/progress_primary_holo_light.9.png
index 6fb9445..bf9f0bf 100644
--- a/core/res/res/drawable-mdpi/progress_primary_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/progress_primary_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progress_secondary_holo_dark.9.png b/core/res/res/drawable-mdpi/progress_secondary_holo_dark.9.png
index 5651a7a..67bd15a 100644
--- a/core/res/res/drawable-mdpi/progress_secondary_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/progress_secondary_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progress_secondary_holo_light.9.png b/core/res/res/drawable-mdpi/progress_secondary_holo_light.9.png
index 9104cf9..4e73f0d 100644
--- a/core/res/res/drawable-mdpi/progress_secondary_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/progress_secondary_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progressbar_indeterminate1.png b/core/res/res/drawable-mdpi/progressbar_indeterminate1.png
index 71780ef..f1b006a 100644
--- a/core/res/res/drawable-mdpi/progressbar_indeterminate1.png
+++ b/core/res/res/drawable-mdpi/progressbar_indeterminate1.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progressbar_indeterminate2.png b/core/res/res/drawable-mdpi/progressbar_indeterminate2.png
index 236988b..4bf8d35 100644
--- a/core/res/res/drawable-mdpi/progressbar_indeterminate2.png
+++ b/core/res/res/drawable-mdpi/progressbar_indeterminate2.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progressbar_indeterminate3.png b/core/res/res/drawable-mdpi/progressbar_indeterminate3.png
index 1570235..23fdd71 100644
--- a/core/res/res/drawable-mdpi/progressbar_indeterminate3.png
+++ b/core/res/res/drawable-mdpi/progressbar_indeterminate3.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo1.png b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo1.png
index df7d06a..1501a1e 100644
--- a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo1.png
+++ b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo1.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo2.png b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo2.png
index b5b933f..1a48587 100644
--- a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo2.png
+++ b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo2.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo3.png b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo3.png
index b4dccc6..71b9ceb 100644
--- a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo3.png
+++ b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo3.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo4.png b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo4.png
index e61f3b3..67353fe 100644
--- a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo4.png
+++ b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo4.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo5.png b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo5.png
index 969ab74..a6c57bb 100644
--- a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo5.png
+++ b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo5.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo6.png b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo6.png
index 5c1aa61..c58a0c84 100644
--- a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo6.png
+++ b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo6.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo7.png b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo7.png
index 0946f2d..0008534 100644
--- a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo7.png
+++ b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo7.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo8.png b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo8.png
index a900c9f..7b24668 100644
--- a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo8.png
+++ b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo8.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/quickactions_arrowdown_left_holo_dark.9.png b/core/res/res/drawable-mdpi/quickactions_arrowdown_left_holo_dark.9.png
index ece6551..392aa91 100644
--- a/core/res/res/drawable-mdpi/quickactions_arrowdown_left_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/quickactions_arrowdown_left_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/quickactions_arrowdown_left_holo_light.9.png b/core/res/res/drawable-mdpi/quickactions_arrowdown_left_holo_light.9.png
index 819656f..b0a145a 100644
--- a/core/res/res/drawable-mdpi/quickactions_arrowdown_left_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/quickactions_arrowdown_left_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/quickactions_arrowdown_right_holo_dark.9.png b/core/res/res/drawable-mdpi/quickactions_arrowdown_right_holo_dark.9.png
index 8e95970..9ad72bc 100644
--- a/core/res/res/drawable-mdpi/quickactions_arrowdown_right_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/quickactions_arrowdown_right_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/quickactions_arrowdown_right_holo_light.9.png b/core/res/res/drawable-mdpi/quickactions_arrowdown_right_holo_light.9.png
index d5bef51..6755c2e 100644
--- a/core/res/res/drawable-mdpi/quickactions_arrowdown_right_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/quickactions_arrowdown_right_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/quickactions_arrowup_left_holo_dark.9.png b/core/res/res/drawable-mdpi/quickactions_arrowup_left_holo_dark.9.png
index 543e341..602e24c 100644
--- a/core/res/res/drawable-mdpi/quickactions_arrowup_left_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/quickactions_arrowup_left_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/quickactions_arrowup_left_holo_light.9.png b/core/res/res/drawable-mdpi/quickactions_arrowup_left_holo_light.9.png
index e40e91d..5feed08 100644
--- a/core/res/res/drawable-mdpi/quickactions_arrowup_left_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/quickactions_arrowup_left_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/quickactions_arrowup_left_right_holo_dark.9.png b/core/res/res/drawable-mdpi/quickactions_arrowup_left_right_holo_dark.9.png
index a4617e7..7d19f04 100644
--- a/core/res/res/drawable-mdpi/quickactions_arrowup_left_right_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/quickactions_arrowup_left_right_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/quickactions_arrowup_right_holo_light.9.png b/core/res/res/drawable-mdpi/quickactions_arrowup_right_holo_light.9.png
index 1e8e7a06..2eeb1727 100644
--- a/core/res/res/drawable-mdpi/quickactions_arrowup_right_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/quickactions_arrowup_right_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_focused_dark_am.9.png b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_focused_dark_am.9.png
index d12a196..3b458d1 100644
--- a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_focused_dark_am.9.png
+++ b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_focused_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_focused_light_am.9.png b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_focused_light_am.9.png
index 27c7977..f03933b 100644
--- a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_focused_light_am.9.png
+++ b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_focused_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_dark_am.9.png b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_dark_am.9.png
index 99c42c5..55a695f 100644
--- a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_dark_am.9.png
+++ b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_light_am.9.png b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_light_am.9.png
index 886b044..5a944d4 100644
--- a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_light_am.9.png
+++ b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_dark_am.9.png b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_dark_am.9.png
index a70615a..4deafae 100644
--- a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_dark_am.9.png
+++ b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_light_am.9.png b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_light_am.9.png
index e7dd785..4cadd52 100644
--- a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_light_am.9.png
+++ b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/radiobutton_off_background.png b/core/res/res/drawable-mdpi/radiobutton_off_background.png
index 1b94e21..b118542 100644
--- a/core/res/res/drawable-mdpi/radiobutton_off_background.png
+++ b/core/res/res/drawable-mdpi/radiobutton_off_background.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/radiobutton_on_background.png b/core/res/res/drawable-mdpi/radiobutton_on_background.png
index 636a803..754468b 100644
--- a/core/res/res/drawable-mdpi/radiobutton_on_background.png
+++ b/core/res/res/drawable-mdpi/radiobutton_on_background.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/rate_star_big_half.png b/core/res/res/drawable-mdpi/rate_star_big_half.png
index 9762292..3cf4d40 100644
--- a/core/res/res/drawable-mdpi/rate_star_big_half.png
+++ b/core/res/res/drawable-mdpi/rate_star_big_half.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/rate_star_big_half_holo_dark.png b/core/res/res/drawable-mdpi/rate_star_big_half_holo_dark.png
index dac51dfd..4972af0 100644
--- a/core/res/res/drawable-mdpi/rate_star_big_half_holo_dark.png
+++ b/core/res/res/drawable-mdpi/rate_star_big_half_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/rate_star_big_half_holo_light.png b/core/res/res/drawable-mdpi/rate_star_big_half_holo_light.png
index 441dbf7..d16ebe4 100644
--- a/core/res/res/drawable-mdpi/rate_star_big_half_holo_light.png
+++ b/core/res/res/drawable-mdpi/rate_star_big_half_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/rate_star_big_off.png b/core/res/res/drawable-mdpi/rate_star_big_off.png
index 6b5039f..88624f9 100644
--- a/core/res/res/drawable-mdpi/rate_star_big_off.png
+++ b/core/res/res/drawable-mdpi/rate_star_big_off.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/rate_star_big_off_holo_dark.png b/core/res/res/drawable-mdpi/rate_star_big_off_holo_dark.png
index cde1fb9..dca1328 100644
--- a/core/res/res/drawable-mdpi/rate_star_big_off_holo_dark.png
+++ b/core/res/res/drawable-mdpi/rate_star_big_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/rate_star_big_off_holo_light.png b/core/res/res/drawable-mdpi/rate_star_big_off_holo_light.png
index 8ecf0f9..cf59df4 100644
--- a/core/res/res/drawable-mdpi/rate_star_big_off_holo_light.png
+++ b/core/res/res/drawable-mdpi/rate_star_big_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/rate_star_big_on.png b/core/res/res/drawable-mdpi/rate_star_big_on.png
index a972db2..1d67160 100644
--- a/core/res/res/drawable-mdpi/rate_star_big_on.png
+++ b/core/res/res/drawable-mdpi/rate_star_big_on.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/rate_star_big_on_holo_dark.png b/core/res/res/drawable-mdpi/rate_star_big_on_holo_dark.png
index 0674db3..9720e59 100644
--- a/core/res/res/drawable-mdpi/rate_star_big_on_holo_dark.png
+++ b/core/res/res/drawable-mdpi/rate_star_big_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/rate_star_big_on_holo_light.png b/core/res/res/drawable-mdpi/rate_star_big_on_holo_light.png
index 0117919..05e033c 100644
--- a/core/res/res/drawable-mdpi/rate_star_big_on_holo_light.png
+++ b/core/res/res/drawable-mdpi/rate_star_big_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/rate_star_med_half.png b/core/res/res/drawable-mdpi/rate_star_med_half.png
index 65a8671..1ec26c3 100644
--- a/core/res/res/drawable-mdpi/rate_star_med_half.png
+++ b/core/res/res/drawable-mdpi/rate_star_med_half.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/rate_star_med_half_holo_dark.png b/core/res/res/drawable-mdpi/rate_star_med_half_holo_dark.png
index f2ce7ab..d05e128 100644
--- a/core/res/res/drawable-mdpi/rate_star_med_half_holo_dark.png
+++ b/core/res/res/drawable-mdpi/rate_star_med_half_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/rate_star_med_half_holo_light.png b/core/res/res/drawable-mdpi/rate_star_med_half_holo_light.png
index 48bcf85..fae6d70 100644
--- a/core/res/res/drawable-mdpi/rate_star_med_half_holo_light.png
+++ b/core/res/res/drawable-mdpi/rate_star_med_half_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/rate_star_med_off.png b/core/res/res/drawable-mdpi/rate_star_med_off.png
index fba0ade..e5c18f4 100644
--- a/core/res/res/drawable-mdpi/rate_star_med_off.png
+++ b/core/res/res/drawable-mdpi/rate_star_med_off.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/rate_star_med_off_holo_dark.png b/core/res/res/drawable-mdpi/rate_star_med_off_holo_dark.png
index d2e7ab6..6b6080e 100644
--- a/core/res/res/drawable-mdpi/rate_star_med_off_holo_dark.png
+++ b/core/res/res/drawable-mdpi/rate_star_med_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/rate_star_med_off_holo_light.png b/core/res/res/drawable-mdpi/rate_star_med_off_holo_light.png
index 69824eb..0dd30e6 100644
--- a/core/res/res/drawable-mdpi/rate_star_med_off_holo_light.png
+++ b/core/res/res/drawable-mdpi/rate_star_med_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/rate_star_med_on.png b/core/res/res/drawable-mdpi/rate_star_med_on.png
index a1941b6..b6e4bfd 100644
--- a/core/res/res/drawable-mdpi/rate_star_med_on.png
+++ b/core/res/res/drawable-mdpi/rate_star_med_on.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/rate_star_med_on_holo_dark.png b/core/res/res/drawable-mdpi/rate_star_med_on_holo_dark.png
index b3b8016..911a8ec 100644
--- a/core/res/res/drawable-mdpi/rate_star_med_on_holo_dark.png
+++ b/core/res/res/drawable-mdpi/rate_star_med_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/rate_star_med_on_holo_light.png b/core/res/res/drawable-mdpi/rate_star_med_on_holo_light.png
index 84ca715..6f0393b 100644
--- a/core/res/res/drawable-mdpi/rate_star_med_on_holo_light.png
+++ b/core/res/res/drawable-mdpi/rate_star_med_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/rate_star_small_half.png b/core/res/res/drawable-mdpi/rate_star_small_half.png
index 437a11c..8da6539 100644
--- a/core/res/res/drawable-mdpi/rate_star_small_half.png
+++ b/core/res/res/drawable-mdpi/rate_star_small_half.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/rate_star_small_half_holo_dark.png b/core/res/res/drawable-mdpi/rate_star_small_half_holo_dark.png
index 56a62d2..590b370 100644
--- a/core/res/res/drawable-mdpi/rate_star_small_half_holo_dark.png
+++ b/core/res/res/drawable-mdpi/rate_star_small_half_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/rate_star_small_half_holo_light.png b/core/res/res/drawable-mdpi/rate_star_small_half_holo_light.png
index 83b7c1c..cad86c4 100644
--- a/core/res/res/drawable-mdpi/rate_star_small_half_holo_light.png
+++ b/core/res/res/drawable-mdpi/rate_star_small_half_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/rate_star_small_off.png b/core/res/res/drawable-mdpi/rate_star_small_off.png
index 6fb0a36..7d3224e 100644
--- a/core/res/res/drawable-mdpi/rate_star_small_off.png
+++ b/core/res/res/drawable-mdpi/rate_star_small_off.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/rate_star_small_off_holo_dark.png b/core/res/res/drawable-mdpi/rate_star_small_off_holo_dark.png
index b70244b..abaeebc 100644
--- a/core/res/res/drawable-mdpi/rate_star_small_off_holo_dark.png
+++ b/core/res/res/drawable-mdpi/rate_star_small_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/rate_star_small_off_holo_light.png b/core/res/res/drawable-mdpi/rate_star_small_off_holo_light.png
index bb5c08c..f182c9c 100644
--- a/core/res/res/drawable-mdpi/rate_star_small_off_holo_light.png
+++ b/core/res/res/drawable-mdpi/rate_star_small_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/rate_star_small_on.png b/core/res/res/drawable-mdpi/rate_star_small_on.png
index 5392361..5af0d62 100644
--- a/core/res/res/drawable-mdpi/rate_star_small_on.png
+++ b/core/res/res/drawable-mdpi/rate_star_small_on.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/rate_star_small_on_holo_dark.png b/core/res/res/drawable-mdpi/rate_star_small_on_holo_dark.png
index 444e882..9eaa3d8b 100644
--- a/core/res/res/drawable-mdpi/rate_star_small_on_holo_dark.png
+++ b/core/res/res/drawable-mdpi/rate_star_small_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/rate_star_small_on_holo_light.png b/core/res/res/drawable-mdpi/rate_star_small_on_holo_light.png
index 7dba529..21bd181 100644
--- a/core/res/res/drawable-mdpi/rate_star_small_on_holo_light.png
+++ b/core/res/res/drawable-mdpi/rate_star_small_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/recent_dialog_background.9.png b/core/res/res/drawable-mdpi/recent_dialog_background.9.png
index 18ed3ff..2c71864 100644
--- a/core/res/res/drawable-mdpi/recent_dialog_background.9.png
+++ b/core/res/res/drawable-mdpi/recent_dialog_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/reticle.png b/core/res/res/drawable-mdpi/reticle.png
index c6ccf8e..6415ca8 100644
--- a/core/res/res/drawable-mdpi/reticle.png
+++ b/core/res/res/drawable-mdpi/reticle.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrollbar_handle_accelerated_anim2.9.png b/core/res/res/drawable-mdpi/scrollbar_handle_accelerated_anim2.9.png
index 6d83bb4..9ff55c3 100644
--- a/core/res/res/drawable-mdpi/scrollbar_handle_accelerated_anim2.9.png
+++ b/core/res/res/drawable-mdpi/scrollbar_handle_accelerated_anim2.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrollbar_handle_holo_dark.9.png b/core/res/res/drawable-mdpi/scrollbar_handle_holo_dark.9.png
index 9407756..3c4bc95 100644
--- a/core/res/res/drawable-mdpi/scrollbar_handle_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/scrollbar_handle_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrollbar_handle_holo_light.9.png b/core/res/res/drawable-mdpi/scrollbar_handle_holo_light.9.png
index d2d0292..8596f8b 100644
--- a/core/res/res/drawable-mdpi/scrollbar_handle_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/scrollbar_handle_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrollbar_handle_horizontal.9.png b/core/res/res/drawable-mdpi/scrollbar_handle_horizontal.9.png
index 8584d1f..55c2c26 100644
--- a/core/res/res/drawable-mdpi/scrollbar_handle_horizontal.9.png
+++ b/core/res/res/drawable-mdpi/scrollbar_handle_horizontal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrollbar_handle_vertical.9.png b/core/res/res/drawable-mdpi/scrollbar_handle_vertical.9.png
index 331a05d..2326ac0 100644
--- a/core/res/res/drawable-mdpi/scrollbar_handle_vertical.9.png
+++ b/core/res/res/drawable-mdpi/scrollbar_handle_vertical.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_control_disabled_holo.png b/core/res/res/drawable-mdpi/scrubber_control_disabled_holo.png
index 630a450..d90dd4d 100644
--- a/core/res/res/drawable-mdpi/scrubber_control_disabled_holo.png
+++ b/core/res/res/drawable-mdpi/scrubber_control_disabled_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_control_focused_holo.png b/core/res/res/drawable-mdpi/scrubber_control_focused_holo.png
index c9e4796..c89b0d0 100644
--- a/core/res/res/drawable-mdpi/scrubber_control_focused_holo.png
+++ b/core/res/res/drawable-mdpi/scrubber_control_focused_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_control_normal_holo.png b/core/res/res/drawable-mdpi/scrubber_control_normal_holo.png
index fb96f4b..eba6229 100644
--- a/core/res/res/drawable-mdpi/scrubber_control_normal_holo.png
+++ b/core/res/res/drawable-mdpi/scrubber_control_normal_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_control_on_mtrl_alpha.png b/core/res/res/drawable-mdpi/scrubber_control_on_mtrl_alpha.png
index 437a3e3..de8ae70 100644
--- a/core/res/res/drawable-mdpi/scrubber_control_on_mtrl_alpha.png
+++ b/core/res/res/drawable-mdpi/scrubber_control_on_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_control_on_pressed_mtrl_alpha.png b/core/res/res/drawable-mdpi/scrubber_control_on_pressed_mtrl_alpha.png
index 3c304bf..bbfd6e0 100644
--- a/core/res/res/drawable-mdpi/scrubber_control_on_pressed_mtrl_alpha.png
+++ b/core/res/res/drawable-mdpi/scrubber_control_on_pressed_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_control_pressed_holo.png b/core/res/res/drawable-mdpi/scrubber_control_pressed_holo.png
index 30e18cd..72e2528 100644
--- a/core/res/res/drawable-mdpi/scrubber_control_pressed_holo.png
+++ b/core/res/res/drawable-mdpi/scrubber_control_pressed_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_primary_holo.9.png b/core/res/res/drawable-mdpi/scrubber_primary_holo.9.png
index a7910d6..5a660d9 100644
--- a/core/res/res/drawable-mdpi/scrubber_primary_holo.9.png
+++ b/core/res/res/drawable-mdpi/scrubber_primary_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_primary_mtrl_alpha.9.png b/core/res/res/drawable-mdpi/scrubber_primary_mtrl_alpha.9.png
index a4ab0a1..b0eb6fb 100644
--- a/core/res/res/drawable-mdpi/scrubber_primary_mtrl_alpha.9.png
+++ b/core/res/res/drawable-mdpi/scrubber_primary_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_secondary_holo.9.png b/core/res/res/drawable-mdpi/scrubber_secondary_holo.9.png
index 985b62e..8abdaea 100644
--- a/core/res/res/drawable-mdpi/scrubber_secondary_holo.9.png
+++ b/core/res/res/drawable-mdpi/scrubber_secondary_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_track_holo_dark.9.png b/core/res/res/drawable-mdpi/scrubber_track_holo_dark.9.png
index b91a4ee..e055e73 100644
--- a/core/res/res/drawable-mdpi/scrubber_track_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/scrubber_track_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_track_holo_light.9.png b/core/res/res/drawable-mdpi/scrubber_track_holo_light.9.png
index 359ae4a..931c23ac 100644
--- a/core/res/res/drawable-mdpi/scrubber_track_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/scrubber_track_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_track_mtrl_alpha.9.png b/core/res/res/drawable-mdpi/scrubber_track_mtrl_alpha.9.png
index db9e172..5409254 100644
--- a/core/res/res/drawable-mdpi/scrubber_track_mtrl_alpha.9.png
+++ b/core/res/res/drawable-mdpi/scrubber_track_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/search_dropdown_background.9.png b/core/res/res/drawable-mdpi/search_dropdown_background.9.png
index 804260a..1664639 100644
--- a/core/res/res/drawable-mdpi/search_dropdown_background.9.png
+++ b/core/res/res/drawable-mdpi/search_dropdown_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/search_plate.9.png b/core/res/res/drawable-mdpi/search_plate.9.png
index 8c42f10..0654b60 100644
--- a/core/res/res/drawable-mdpi/search_plate.9.png
+++ b/core/res/res/drawable-mdpi/search_plate.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/search_plate_global.9.png b/core/res/res/drawable-mdpi/search_plate_global.9.png
index 1cad902..bfbecda 100644
--- a/core/res/res/drawable-mdpi/search_plate_global.9.png
+++ b/core/res/res/drawable-mdpi/search_plate_global.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/seek_thumb_normal.png b/core/res/res/drawable-mdpi/seek_thumb_normal.png
index e9f2e23..16faaee 100644
--- a/core/res/res/drawable-mdpi/seek_thumb_normal.png
+++ b/core/res/res/drawable-mdpi/seek_thumb_normal.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/seek_thumb_pressed.png b/core/res/res/drawable-mdpi/seek_thumb_pressed.png
index 3ea5051..0f1bbc5 100644
--- a/core/res/res/drawable-mdpi/seek_thumb_pressed.png
+++ b/core/res/res/drawable-mdpi/seek_thumb_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/seek_thumb_selected.png b/core/res/res/drawable-mdpi/seek_thumb_selected.png
index 98b7ba0..a635a6f 100644
--- a/core/res/res/drawable-mdpi/seek_thumb_selected.png
+++ b/core/res/res/drawable-mdpi/seek_thumb_selected.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/settings_header_raw.9.png b/core/res/res/drawable-mdpi/settings_header_raw.9.png
index 6b8134d..2bd4753 100644
--- a/core/res/res/drawable-mdpi/settings_header_raw.9.png
+++ b/core/res/res/drawable-mdpi/settings_header_raw.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sim_dark_blue.9.png b/core/res/res/drawable-mdpi/sim_dark_blue.9.png
index d646a7f..2c217ef 100644
--- a/core/res/res/drawable-mdpi/sim_dark_blue.9.png
+++ b/core/res/res/drawable-mdpi/sim_dark_blue.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sim_dark_green.9.png b/core/res/res/drawable-mdpi/sim_dark_green.9.png
index ee4ea0d..b620ce0 100644
--- a/core/res/res/drawable-mdpi/sim_dark_green.9.png
+++ b/core/res/res/drawable-mdpi/sim_dark_green.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sim_dark_orange.9.png b/core/res/res/drawable-mdpi/sim_dark_orange.9.png
index b394999..f655367 100644
--- a/core/res/res/drawable-mdpi/sim_dark_orange.9.png
+++ b/core/res/res/drawable-mdpi/sim_dark_orange.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sim_dark_purple.9.png b/core/res/res/drawable-mdpi/sim_dark_purple.9.png
index 459b5d6..f816705 100644
--- a/core/res/res/drawable-mdpi/sim_dark_purple.9.png
+++ b/core/res/res/drawable-mdpi/sim_dark_purple.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sim_light_blue.9.png b/core/res/res/drawable-mdpi/sim_light_blue.9.png
index 396ad70..c483e22 100644
--- a/core/res/res/drawable-mdpi/sim_light_blue.9.png
+++ b/core/res/res/drawable-mdpi/sim_light_blue.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sim_light_green.9.png b/core/res/res/drawable-mdpi/sim_light_green.9.png
index a063174..ddafeb3 100644
--- a/core/res/res/drawable-mdpi/sim_light_green.9.png
+++ b/core/res/res/drawable-mdpi/sim_light_green.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sim_light_orange.9.png b/core/res/res/drawable-mdpi/sim_light_orange.9.png
index 95ea88e..ddd5e86 100644
--- a/core/res/res/drawable-mdpi/sim_light_orange.9.png
+++ b/core/res/res/drawable-mdpi/sim_light_orange.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sim_light_purple.9.png b/core/res/res/drawable-mdpi/sim_light_purple.9.png
index b1bd35f..a392f99 100644
--- a/core/res/res/drawable-mdpi/sim_light_purple.9.png
+++ b/core/res/res/drawable-mdpi/sim_light_purple.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_16_inner_holo.png b/core/res/res/drawable-mdpi/spinner_16_inner_holo.png
index eeef0c8..177bc3d 100644
--- a/core/res/res/drawable-mdpi/spinner_16_inner_holo.png
+++ b/core/res/res/drawable-mdpi/spinner_16_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_16_outer_holo.png b/core/res/res/drawable-mdpi/spinner_16_outer_holo.png
index 7cc2b54..27d5f1f 100644
--- a/core/res/res/drawable-mdpi/spinner_16_outer_holo.png
+++ b/core/res/res/drawable-mdpi/spinner_16_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_48_inner_holo.png b/core/res/res/drawable-mdpi/spinner_48_inner_holo.png
index 9458668..1b9dc2e 100644
--- a/core/res/res/drawable-mdpi/spinner_48_inner_holo.png
+++ b/core/res/res/drawable-mdpi/spinner_48_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_48_outer_holo.png b/core/res/res/drawable-mdpi/spinner_48_outer_holo.png
index 4ce73ed..30d288d 100644
--- a/core/res/res/drawable-mdpi/spinner_48_outer_holo.png
+++ b/core/res/res/drawable-mdpi/spinner_48_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_76_inner_holo.png b/core/res/res/drawable-mdpi/spinner_76_inner_holo.png
index cba1300d..9cdeb21 100644
--- a/core/res/res/drawable-mdpi/spinner_76_inner_holo.png
+++ b/core/res/res/drawable-mdpi/spinner_76_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_76_outer_holo.png b/core/res/res/drawable-mdpi/spinner_76_outer_holo.png
index 99a5ebb..19e7662 100644
--- a/core/res/res/drawable-mdpi/spinner_76_outer_holo.png
+++ b/core/res/res/drawable-mdpi/spinner_76_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_ab_default_holo_dark_am.9.png b/core/res/res/drawable-mdpi/spinner_ab_default_holo_dark_am.9.png
index 8d75946..5092a20 100644
--- a/core/res/res/drawable-mdpi/spinner_ab_default_holo_dark_am.9.png
+++ b/core/res/res/drawable-mdpi/spinner_ab_default_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_ab_default_holo_light_am.9.png b/core/res/res/drawable-mdpi/spinner_ab_default_holo_light_am.9.png
index 716560b..e11a74d 100644
--- a/core/res/res/drawable-mdpi/spinner_ab_default_holo_light_am.9.png
+++ b/core/res/res/drawable-mdpi/spinner_ab_default_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_ab_disabled_holo_dark_am.9.png b/core/res/res/drawable-mdpi/spinner_ab_disabled_holo_dark_am.9.png
index c3ba89c..b2e0426 100644
--- a/core/res/res/drawable-mdpi/spinner_ab_disabled_holo_dark_am.9.png
+++ b/core/res/res/drawable-mdpi/spinner_ab_disabled_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_ab_disabled_holo_light_am.9.png b/core/res/res/drawable-mdpi/spinner_ab_disabled_holo_light_am.9.png
index 67c5358..6bb86bf 100644
--- a/core/res/res/drawable-mdpi/spinner_ab_disabled_holo_light_am.9.png
+++ b/core/res/res/drawable-mdpi/spinner_ab_disabled_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_ab_focused_holo_dark_am.9.png b/core/res/res/drawable-mdpi/spinner_ab_focused_holo_dark_am.9.png
index c015f43..2d971e3 100644
--- a/core/res/res/drawable-mdpi/spinner_ab_focused_holo_dark_am.9.png
+++ b/core/res/res/drawable-mdpi/spinner_ab_focused_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_ab_focused_holo_light_am.9.png b/core/res/res/drawable-mdpi/spinner_ab_focused_holo_light_am.9.png
index 487edc2..391c386 100644
--- a/core/res/res/drawable-mdpi/spinner_ab_focused_holo_light_am.9.png
+++ b/core/res/res/drawable-mdpi/spinner_ab_focused_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_dark_am.9.png b/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_dark_am.9.png
index b21c73c..6370582 100644
--- a/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_dark_am.9.png
+++ b/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_light_am.9.png b/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_light_am.9.png
index 58904e8..4e1ec6d 100644
--- a/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_light_am.9.png
+++ b/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_black_16.png b/core/res/res/drawable-mdpi/spinner_black_16.png
index 4b7fdfe..47145a3 100644
--- a/core/res/res/drawable-mdpi/spinner_black_16.png
+++ b/core/res/res/drawable-mdpi/spinner_black_16.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_black_20.png b/core/res/res/drawable-mdpi/spinner_black_20.png
index 86d7a20..c7a7b3e 100644
--- a/core/res/res/drawable-mdpi/spinner_black_20.png
+++ b/core/res/res/drawable-mdpi/spinner_black_20.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_black_48.png b/core/res/res/drawable-mdpi/spinner_black_48.png
index f1571f9..10fa1f5 100644
--- a/core/res/res/drawable-mdpi/spinner_black_48.png
+++ b/core/res/res/drawable-mdpi/spinner_black_48.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_black_76.png b/core/res/res/drawable-mdpi/spinner_black_76.png
index e9f6e8f..02ba2a3 100644
--- a/core/res/res/drawable-mdpi/spinner_black_76.png
+++ b/core/res/res/drawable-mdpi/spinner_black_76.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_default_holo_dark_am.9.png b/core/res/res/drawable-mdpi/spinner_default_holo_dark_am.9.png
index 5ac84dd..b5e9dc5 100644
--- a/core/res/res/drawable-mdpi/spinner_default_holo_dark_am.9.png
+++ b/core/res/res/drawable-mdpi/spinner_default_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_default_holo_light_am.9.png b/core/res/res/drawable-mdpi/spinner_default_holo_light_am.9.png
index 3eeebc4..b1341d0 100644
--- a/core/res/res/drawable-mdpi/spinner_default_holo_light_am.9.png
+++ b/core/res/res/drawable-mdpi/spinner_default_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_disabled_holo_dark_am.9.png b/core/res/res/drawable-mdpi/spinner_disabled_holo_dark_am.9.png
index 2734f20..41011d3 100644
--- a/core/res/res/drawable-mdpi/spinner_disabled_holo_dark_am.9.png
+++ b/core/res/res/drawable-mdpi/spinner_disabled_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_disabled_holo_light_am.9.png b/core/res/res/drawable-mdpi/spinner_disabled_holo_light_am.9.png
index a78d6c0..8177fb3 100644
--- a/core/res/res/drawable-mdpi/spinner_disabled_holo_light_am.9.png
+++ b/core/res/res/drawable-mdpi/spinner_disabled_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_dropdown_background_down.9.png b/core/res/res/drawable-mdpi/spinner_dropdown_background_down.9.png
index 8fd22f4..30fe1b8 100644
--- a/core/res/res/drawable-mdpi/spinner_dropdown_background_down.9.png
+++ b/core/res/res/drawable-mdpi/spinner_dropdown_background_down.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_dropdown_background_up.9.png b/core/res/res/drawable-mdpi/spinner_dropdown_background_up.9.png
index 1354feb..a734e6a 100644
--- a/core/res/res/drawable-mdpi/spinner_dropdown_background_up.9.png
+++ b/core/res/res/drawable-mdpi/spinner_dropdown_background_up.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_focused_holo_dark_am.9.png b/core/res/res/drawable-mdpi/spinner_focused_holo_dark_am.9.png
index 7d91915..42cdc09 100644
--- a/core/res/res/drawable-mdpi/spinner_focused_holo_dark_am.9.png
+++ b/core/res/res/drawable-mdpi/spinner_focused_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_focused_holo_light_am.9.png b/core/res/res/drawable-mdpi/spinner_focused_holo_light_am.9.png
index d7c4b87..f2c49c9 100644
--- a/core/res/res/drawable-mdpi/spinner_focused_holo_light_am.9.png
+++ b/core/res/res/drawable-mdpi/spinner_focused_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_normal.9.png b/core/res/res/drawable-mdpi/spinner_normal.9.png
index e0bab34..773d0aa 100644
--- a/core/res/res/drawable-mdpi/spinner_normal.9.png
+++ b/core/res/res/drawable-mdpi/spinner_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_press.9.png b/core/res/res/drawable-mdpi/spinner_press.9.png
index a51c7ad..79c3f5e 100644
--- a/core/res/res/drawable-mdpi/spinner_press.9.png
+++ b/core/res/res/drawable-mdpi/spinner_press.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_pressed_holo_dark_am.9.png b/core/res/res/drawable-mdpi/spinner_pressed_holo_dark_am.9.png
index 75fb81e..fb67d8f 100644
--- a/core/res/res/drawable-mdpi/spinner_pressed_holo_dark_am.9.png
+++ b/core/res/res/drawable-mdpi/spinner_pressed_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_pressed_holo_light_am.9.png b/core/res/res/drawable-mdpi/spinner_pressed_holo_light_am.9.png
index fdd88b5..895a08c 100644
--- a/core/res/res/drawable-mdpi/spinner_pressed_holo_light_am.9.png
+++ b/core/res/res/drawable-mdpi/spinner_pressed_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_select.9.png b/core/res/res/drawable-mdpi/spinner_select.9.png
index 1bb19be..bf9fe4a 100644
--- a/core/res/res/drawable-mdpi/spinner_select.9.png
+++ b/core/res/res/drawable-mdpi/spinner_select.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_white_16.png b/core/res/res/drawable-mdpi/spinner_white_16.png
index 650e315..76b0709 100644
--- a/core/res/res/drawable-mdpi/spinner_white_16.png
+++ b/core/res/res/drawable-mdpi/spinner_white_16.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_white_48.png b/core/res/res/drawable-mdpi/spinner_white_48.png
index 11eacf8..80d6bcf 100644
--- a/core/res/res/drawable-mdpi/spinner_white_48.png
+++ b/core/res/res/drawable-mdpi/spinner_white_48.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_white_76.png b/core/res/res/drawable-mdpi/spinner_white_76.png
index 6c31bc3..a854c7c 100644
--- a/core/res/res/drawable-mdpi/spinner_white_76.png
+++ b/core/res/res/drawable-mdpi/spinner_white_76.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/star_big_off.png b/core/res/res/drawable-mdpi/star_big_off.png
index 34ab4ab..95b2cf2 100644
--- a/core/res/res/drawable-mdpi/star_big_off.png
+++ b/core/res/res/drawable-mdpi/star_big_off.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/star_big_on.png b/core/res/res/drawable-mdpi/star_big_on.png
index 7aaf2bc..6e16878 100644
--- a/core/res/res/drawable-mdpi/star_big_on.png
+++ b/core/res/res/drawable-mdpi/star_big_on.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/star_off.png b/core/res/res/drawable-mdpi/star_off.png
index ada53fc..16baeb8 100644
--- a/core/res/res/drawable-mdpi/star_off.png
+++ b/core/res/res/drawable-mdpi/star_off.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/star_on.png b/core/res/res/drawable-mdpi/star_on.png
index 49a57b6..97bbe3c 100644
--- a/core/res/res/drawable-mdpi/star_on.png
+++ b/core/res/res/drawable-mdpi/star_on.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_ecb_mode.png b/core/res/res/drawable-mdpi/stat_ecb_mode.png
index a948770..14f6038 100644
--- a/core/res/res/drawable-mdpi/stat_ecb_mode.png
+++ b/core/res/res/drawable-mdpi/stat_ecb_mode.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_car_mode.png b/core/res/res/drawable-mdpi/stat_notify_car_mode.png
index d8015dc..3ea8f9b 100644
--- a/core/res/res/drawable-mdpi/stat_notify_car_mode.png
+++ b/core/res/res/drawable-mdpi/stat_notify_car_mode.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_chat.png b/core/res/res/drawable-mdpi/stat_notify_chat.png
index 4ff4667..4a60dbc 100644
--- a/core/res/res/drawable-mdpi/stat_notify_chat.png
+++ b/core/res/res/drawable-mdpi/stat_notify_chat.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_disk_full.png b/core/res/res/drawable-mdpi/stat_notify_disk_full.png
index 392e7bf..5ac3a9b 100644
--- a/core/res/res/drawable-mdpi/stat_notify_disk_full.png
+++ b/core/res/res/drawable-mdpi/stat_notify_disk_full.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_email_generic.png b/core/res/res/drawable-mdpi/stat_notify_email_generic.png
index 7732c10..de1a3fe 100644
--- a/core/res/res/drawable-mdpi/stat_notify_email_generic.png
+++ b/core/res/res/drawable-mdpi/stat_notify_email_generic.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_error.png b/core/res/res/drawable-mdpi/stat_notify_error.png
index 78d59aa..89ac3c6 100644
--- a/core/res/res/drawable-mdpi/stat_notify_error.png
+++ b/core/res/res/drawable-mdpi/stat_notify_error.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_gmail.png b/core/res/res/drawable-mdpi/stat_notify_gmail.png
index 47ee782..7983ecf 100644
--- a/core/res/res/drawable-mdpi/stat_notify_gmail.png
+++ b/core/res/res/drawable-mdpi/stat_notify_gmail.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_missed_call.png b/core/res/res/drawable-mdpi/stat_notify_missed_call.png
index f2ff56e..afa65b8 100644
--- a/core/res/res/drawable-mdpi/stat_notify_missed_call.png
+++ b/core/res/res/drawable-mdpi/stat_notify_missed_call.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_more.png b/core/res/res/drawable-mdpi/stat_notify_more.png
index 52b40f8..ddb61f9 100644
--- a/core/res/res/drawable-mdpi/stat_notify_more.png
+++ b/core/res/res/drawable-mdpi/stat_notify_more.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_rssi_in_range.png b/core/res/res/drawable-mdpi/stat_notify_rssi_in_range.png
index 62e4fe9..f30ca98 100644
--- a/core/res/res/drawable-mdpi/stat_notify_rssi_in_range.png
+++ b/core/res/res/drawable-mdpi/stat_notify_rssi_in_range.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_sdcard.png b/core/res/res/drawable-mdpi/stat_notify_sdcard.png
index 5eae7a2..17f2cb8 100644
--- a/core/res/res/drawable-mdpi/stat_notify_sdcard.png
+++ b/core/res/res/drawable-mdpi/stat_notify_sdcard.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_sdcard_prepare.png b/core/res/res/drawable-mdpi/stat_notify_sdcard_prepare.png
index a7a8b5c..d1a1045 100644
--- a/core/res/res/drawable-mdpi/stat_notify_sdcard_prepare.png
+++ b/core/res/res/drawable-mdpi/stat_notify_sdcard_prepare.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_sdcard_usb.png b/core/res/res/drawable-mdpi/stat_notify_sdcard_usb.png
index 6f17feb..9ff53c0 100644
--- a/core/res/res/drawable-mdpi/stat_notify_sdcard_usb.png
+++ b/core/res/res/drawable-mdpi/stat_notify_sdcard_usb.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_sim_toolkit.png b/core/res/res/drawable-mdpi/stat_notify_sim_toolkit.png
index 6a774cf..c600d41 100644
--- a/core/res/res/drawable-mdpi/stat_notify_sim_toolkit.png
+++ b/core/res/res/drawable-mdpi/stat_notify_sim_toolkit.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_sync.png b/core/res/res/drawable-mdpi/stat_notify_sync.png
index 1be8677..35f5191 100644
--- a/core/res/res/drawable-mdpi/stat_notify_sync.png
+++ b/core/res/res/drawable-mdpi/stat_notify_sync.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_sync_anim0.png b/core/res/res/drawable-mdpi/stat_notify_sync_anim0.png
index 1be8677..35f5191 100644
--- a/core/res/res/drawable-mdpi/stat_notify_sync_anim0.png
+++ b/core/res/res/drawable-mdpi/stat_notify_sync_anim0.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_sync_error.png b/core/res/res/drawable-mdpi/stat_notify_sync_error.png
index 30658c5..21ae370 100644
--- a/core/res/res/drawable-mdpi/stat_notify_sync_error.png
+++ b/core/res/res/drawable-mdpi/stat_notify_sync_error.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_voicemail.png b/core/res/res/drawable-mdpi/stat_notify_voicemail.png
index dd70146..e869c2b 100644
--- a/core/res/res/drawable-mdpi/stat_notify_voicemail.png
+++ b/core/res/res/drawable-mdpi/stat_notify_voicemail.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_0.png b/core/res/res/drawable-mdpi/stat_sys_battery_0.png
index e089120..c6a8f68 100644
--- a/core/res/res/drawable-mdpi/stat_sys_battery_0.png
+++ b/core/res/res/drawable-mdpi/stat_sys_battery_0.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_100.png b/core/res/res/drawable-mdpi/stat_sys_battery_100.png
index 70d7fa4..6ba5072 100644
--- a/core/res/res/drawable-mdpi/stat_sys_battery_100.png
+++ b/core/res/res/drawable-mdpi/stat_sys_battery_100.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_15.png b/core/res/res/drawable-mdpi/stat_sys_battery_15.png
index be04321..32a700b 100644
--- a/core/res/res/drawable-mdpi/stat_sys_battery_15.png
+++ b/core/res/res/drawable-mdpi/stat_sys_battery_15.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_28.png b/core/res/res/drawable-mdpi/stat_sys_battery_28.png
index f634dde..7c6b1a8 100644
--- a/core/res/res/drawable-mdpi/stat_sys_battery_28.png
+++ b/core/res/res/drawable-mdpi/stat_sys_battery_28.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_43.png b/core/res/res/drawable-mdpi/stat_sys_battery_43.png
index f0376bd..148a8d1 100644
--- a/core/res/res/drawable-mdpi/stat_sys_battery_43.png
+++ b/core/res/res/drawable-mdpi/stat_sys_battery_43.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_57.png b/core/res/res/drawable-mdpi/stat_sys_battery_57.png
index 840af66..3afa460 100644
--- a/core/res/res/drawable-mdpi/stat_sys_battery_57.png
+++ b/core/res/res/drawable-mdpi/stat_sys_battery_57.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_71.png b/core/res/res/drawable-mdpi/stat_sys_battery_71.png
index 04c3569..01b5529 100644
--- a/core/res/res/drawable-mdpi/stat_sys_battery_71.png
+++ b/core/res/res/drawable-mdpi/stat_sys_battery_71.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_85.png b/core/res/res/drawable-mdpi/stat_sys_battery_85.png
index c742da7..e18357e 100644
--- a/core/res/res/drawable-mdpi/stat_sys_battery_85.png
+++ b/core/res/res/drawable-mdpi/stat_sys_battery_85.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim0.png b/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim0.png
index f8011c9..d08e979 100644
--- a/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim0.png
+++ b/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim0.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim100.png b/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim100.png
index 499ced9..14a30de 100644
--- a/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim100.png
+++ b/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim100.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim15.png b/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim15.png
index c921d6a..580b12b 100644
--- a/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim15.png
+++ b/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim15.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim28.png b/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim28.png
index f882002..6830ea3 100644
--- a/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim28.png
+++ b/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim28.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim43.png b/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim43.png
index e7d1069..1bb47cb 100644
--- a/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim43.png
+++ b/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim43.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim57.png b/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim57.png
index 5e0af3d..0a0e821 100644
--- a/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim57.png
+++ b/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim57.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim71.png b/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim71.png
index fb99059..299c46b 100644
--- a/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim71.png
+++ b/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim71.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim85.png b/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim85.png
index 072f907..9f6069b 100644
--- a/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim85.png
+++ b/core/res/res/drawable-mdpi/stat_sys_battery_charge_anim85.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_battery_unknown.png b/core/res/res/drawable-mdpi/stat_sys_battery_unknown.png
index 3984c46..0f9d0fa7 100644
--- a/core/res/res/drawable-mdpi/stat_sys_battery_unknown.png
+++ b/core/res/res/drawable-mdpi/stat_sys_battery_unknown.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_certificate_info.png b/core/res/res/drawable-mdpi/stat_sys_certificate_info.png
index e15cf38..5acba7b 100644
--- a/core/res/res/drawable-mdpi/stat_sys_certificate_info.png
+++ b/core/res/res/drawable-mdpi/stat_sys_certificate_info.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_data_bluetooth.png b/core/res/res/drawable-mdpi/stat_sys_data_bluetooth.png
index 68fe66a..2556b48 100644
--- a/core/res/res/drawable-mdpi/stat_sys_data_bluetooth.png
+++ b/core/res/res/drawable-mdpi/stat_sys_data_bluetooth.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_data_usb.png b/core/res/res/drawable-mdpi/stat_sys_data_usb.png
index 40d77f0..9294e5f 100644
--- a/core/res/res/drawable-mdpi/stat_sys_data_usb.png
+++ b/core/res/res/drawable-mdpi/stat_sys_data_usb.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_data_wimax_signal_3_fully.png b/core/res/res/drawable-mdpi/stat_sys_data_wimax_signal_3_fully.png
index d3ba98c..ed1a223 100644
--- a/core/res/res/drawable-mdpi/stat_sys_data_wimax_signal_3_fully.png
+++ b/core/res/res/drawable-mdpi/stat_sys_data_wimax_signal_3_fully.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_data_wimax_signal_disconnected.png b/core/res/res/drawable-mdpi/stat_sys_data_wimax_signal_disconnected.png
index 153c6ad..01d32f6 100644
--- a/core/res/res/drawable-mdpi/stat_sys_data_wimax_signal_disconnected.png
+++ b/core/res/res/drawable-mdpi/stat_sys_data_wimax_signal_disconnected.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_download_anim0.png b/core/res/res/drawable-mdpi/stat_sys_download_anim0.png
index 25324f6..3758712 100644
--- a/core/res/res/drawable-mdpi/stat_sys_download_anim0.png
+++ b/core/res/res/drawable-mdpi/stat_sys_download_anim0.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_download_anim1.png b/core/res/res/drawable-mdpi/stat_sys_download_anim1.png
index 6d1fb4a..385e1e0 100644
--- a/core/res/res/drawable-mdpi/stat_sys_download_anim1.png
+++ b/core/res/res/drawable-mdpi/stat_sys_download_anim1.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_download_anim2.png b/core/res/res/drawable-mdpi/stat_sys_download_anim2.png
index 4c3e963..0352e91 100644
--- a/core/res/res/drawable-mdpi/stat_sys_download_anim2.png
+++ b/core/res/res/drawable-mdpi/stat_sys_download_anim2.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_download_anim3.png b/core/res/res/drawable-mdpi/stat_sys_download_anim3.png
index 2aae625..b1fbd5c 100644
--- a/core/res/res/drawable-mdpi/stat_sys_download_anim3.png
+++ b/core/res/res/drawable-mdpi/stat_sys_download_anim3.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_download_anim4.png b/core/res/res/drawable-mdpi/stat_sys_download_anim4.png
index 55dbe12..29c701a 100644
--- a/core/res/res/drawable-mdpi/stat_sys_download_anim4.png
+++ b/core/res/res/drawable-mdpi/stat_sys_download_anim4.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_download_anim5.png b/core/res/res/drawable-mdpi/stat_sys_download_anim5.png
index 53fda44..885ba80 100644
--- a/core/res/res/drawable-mdpi/stat_sys_download_anim5.png
+++ b/core/res/res/drawable-mdpi/stat_sys_download_anim5.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_gps_on.png b/core/res/res/drawable-mdpi/stat_sys_gps_on.png
index 311a1de..54d6ea8 100644
--- a/core/res/res/drawable-mdpi/stat_sys_gps_on.png
+++ b/core/res/res/drawable-mdpi/stat_sys_gps_on.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_headset.png b/core/res/res/drawable-mdpi/stat_sys_headset.png
index 45fbea2..4a59cd6 100644
--- a/core/res/res/drawable-mdpi/stat_sys_headset.png
+++ b/core/res/res/drawable-mdpi/stat_sys_headset.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_phone_call.png b/core/res/res/drawable-mdpi/stat_sys_phone_call.png
index 71da6a2..df8d0ce 100644
--- a/core/res/res/drawable-mdpi/stat_sys_phone_call.png
+++ b/core/res/res/drawable-mdpi/stat_sys_phone_call.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_phone_call_forward.png b/core/res/res/drawable-mdpi/stat_sys_phone_call_forward.png
index b0dbe6d..f969335 100644
--- a/core/res/res/drawable-mdpi/stat_sys_phone_call_forward.png
+++ b/core/res/res/drawable-mdpi/stat_sys_phone_call_forward.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_phone_call_on_hold.png b/core/res/res/drawable-mdpi/stat_sys_phone_call_on_hold.png
index 22e9082..7ba8508 100644
--- a/core/res/res/drawable-mdpi/stat_sys_phone_call_on_hold.png
+++ b/core/res/res/drawable-mdpi/stat_sys_phone_call_on_hold.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_r_signal_0_cdma.png b/core/res/res/drawable-mdpi/stat_sys_r_signal_0_cdma.png
index f39f5ba..7f8b966 100644
--- a/core/res/res/drawable-mdpi/stat_sys_r_signal_0_cdma.png
+++ b/core/res/res/drawable-mdpi/stat_sys_r_signal_0_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_r_signal_1_cdma.png b/core/res/res/drawable-mdpi/stat_sys_r_signal_1_cdma.png
index 86bb2de..94566f1 100644
--- a/core/res/res/drawable-mdpi/stat_sys_r_signal_1_cdma.png
+++ b/core/res/res/drawable-mdpi/stat_sys_r_signal_1_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_r_signal_2_cdma.png b/core/res/res/drawable-mdpi/stat_sys_r_signal_2_cdma.png
index b6eda07..9934b9e 100644
--- a/core/res/res/drawable-mdpi/stat_sys_r_signal_2_cdma.png
+++ b/core/res/res/drawable-mdpi/stat_sys_r_signal_2_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_r_signal_3_cdma.png b/core/res/res/drawable-mdpi/stat_sys_r_signal_3_cdma.png
index b7ca7f9..a9fa0ed 100644
--- a/core/res/res/drawable-mdpi/stat_sys_r_signal_3_cdma.png
+++ b/core/res/res/drawable-mdpi/stat_sys_r_signal_3_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_r_signal_4_cdma.png b/core/res/res/drawable-mdpi/stat_sys_r_signal_4_cdma.png
index 61a9575..6351849 100644
--- a/core/res/res/drawable-mdpi/stat_sys_r_signal_4_cdma.png
+++ b/core/res/res/drawable-mdpi/stat_sys_r_signal_4_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_ra_signal_0_cdma.png b/core/res/res/drawable-mdpi/stat_sys_ra_signal_0_cdma.png
index feb4f2c..a9abd91 100644
--- a/core/res/res/drawable-mdpi/stat_sys_ra_signal_0_cdma.png
+++ b/core/res/res/drawable-mdpi/stat_sys_ra_signal_0_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_ra_signal_1_cdma.png b/core/res/res/drawable-mdpi/stat_sys_ra_signal_1_cdma.png
index a42ff0c..cb0dc45f 100644
--- a/core/res/res/drawable-mdpi/stat_sys_ra_signal_1_cdma.png
+++ b/core/res/res/drawable-mdpi/stat_sys_ra_signal_1_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_ra_signal_2_cdma.png b/core/res/res/drawable-mdpi/stat_sys_ra_signal_2_cdma.png
index e991c76..2347e0d 100644
--- a/core/res/res/drawable-mdpi/stat_sys_ra_signal_2_cdma.png
+++ b/core/res/res/drawable-mdpi/stat_sys_ra_signal_2_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_ra_signal_3_cdma.png b/core/res/res/drawable-mdpi/stat_sys_ra_signal_3_cdma.png
index 4b743fb..ec3d915 100644
--- a/core/res/res/drawable-mdpi/stat_sys_ra_signal_3_cdma.png
+++ b/core/res/res/drawable-mdpi/stat_sys_ra_signal_3_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_ra_signal_4_cdma.png b/core/res/res/drawable-mdpi/stat_sys_ra_signal_4_cdma.png
index 65172b7..53e5165 100644
--- a/core/res/res/drawable-mdpi/stat_sys_ra_signal_4_cdma.png
+++ b/core/res/res/drawable-mdpi/stat_sys_ra_signal_4_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_signal_0_cdma.png b/core/res/res/drawable-mdpi/stat_sys_signal_0_cdma.png
index 03c51ce..e441de9 100644
--- a/core/res/res/drawable-mdpi/stat_sys_signal_0_cdma.png
+++ b/core/res/res/drawable-mdpi/stat_sys_signal_0_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_signal_1_cdma.png b/core/res/res/drawable-mdpi/stat_sys_signal_1_cdma.png
index dced6df..fbbe7f4 100644
--- a/core/res/res/drawable-mdpi/stat_sys_signal_1_cdma.png
+++ b/core/res/res/drawable-mdpi/stat_sys_signal_1_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_signal_2_cdma.png b/core/res/res/drawable-mdpi/stat_sys_signal_2_cdma.png
index 9eac4c6..7b24078 100644
--- a/core/res/res/drawable-mdpi/stat_sys_signal_2_cdma.png
+++ b/core/res/res/drawable-mdpi/stat_sys_signal_2_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_signal_3_cdma.png b/core/res/res/drawable-mdpi/stat_sys_signal_3_cdma.png
index 74d983c..575a12a 100644
--- a/core/res/res/drawable-mdpi/stat_sys_signal_3_cdma.png
+++ b/core/res/res/drawable-mdpi/stat_sys_signal_3_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_signal_4_cdma.png b/core/res/res/drawable-mdpi/stat_sys_signal_4_cdma.png
index 8cc40b5..db7182b 100644
--- a/core/res/res/drawable-mdpi/stat_sys_signal_4_cdma.png
+++ b/core/res/res/drawable-mdpi/stat_sys_signal_4_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_signal_evdo_0.png b/core/res/res/drawable-mdpi/stat_sys_signal_evdo_0.png
index 177e0e9..28b35b0 100644
--- a/core/res/res/drawable-mdpi/stat_sys_signal_evdo_0.png
+++ b/core/res/res/drawable-mdpi/stat_sys_signal_evdo_0.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_signal_evdo_1.png b/core/res/res/drawable-mdpi/stat_sys_signal_evdo_1.png
index 5f66319..97932c8 100644
--- a/core/res/res/drawable-mdpi/stat_sys_signal_evdo_1.png
+++ b/core/res/res/drawable-mdpi/stat_sys_signal_evdo_1.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_signal_evdo_2.png b/core/res/res/drawable-mdpi/stat_sys_signal_evdo_2.png
index c365912..6bfd946 100644
--- a/core/res/res/drawable-mdpi/stat_sys_signal_evdo_2.png
+++ b/core/res/res/drawable-mdpi/stat_sys_signal_evdo_2.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_signal_evdo_3.png b/core/res/res/drawable-mdpi/stat_sys_signal_evdo_3.png
index 58d631b..2df61e9 100644
--- a/core/res/res/drawable-mdpi/stat_sys_signal_evdo_3.png
+++ b/core/res/res/drawable-mdpi/stat_sys_signal_evdo_3.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_signal_evdo_4.png b/core/res/res/drawable-mdpi/stat_sys_signal_evdo_4.png
index e63af68..000d6f7 100644
--- a/core/res/res/drawable-mdpi/stat_sys_signal_evdo_4.png
+++ b/core/res/res/drawable-mdpi/stat_sys_signal_evdo_4.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_throttled.png b/core/res/res/drawable-mdpi/stat_sys_throttled.png
index ef6a7af..3a89fdf 100644
--- a/core/res/res/drawable-mdpi/stat_sys_throttled.png
+++ b/core/res/res/drawable-mdpi/stat_sys_throttled.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_upload_anim0.png b/core/res/res/drawable-mdpi/stat_sys_upload_anim0.png
index 6402aa5..b0bef71 100644
--- a/core/res/res/drawable-mdpi/stat_sys_upload_anim0.png
+++ b/core/res/res/drawable-mdpi/stat_sys_upload_anim0.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_upload_anim1.png b/core/res/res/drawable-mdpi/stat_sys_upload_anim1.png
index 217ea4e..5d00d08 100644
--- a/core/res/res/drawable-mdpi/stat_sys_upload_anim1.png
+++ b/core/res/res/drawable-mdpi/stat_sys_upload_anim1.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_upload_anim2.png b/core/res/res/drawable-mdpi/stat_sys_upload_anim2.png
index b9c364c..c71e759 100644
--- a/core/res/res/drawable-mdpi/stat_sys_upload_anim2.png
+++ b/core/res/res/drawable-mdpi/stat_sys_upload_anim2.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_upload_anim3.png b/core/res/res/drawable-mdpi/stat_sys_upload_anim3.png
index e22ec6d..426a626 100644
--- a/core/res/res/drawable-mdpi/stat_sys_upload_anim3.png
+++ b/core/res/res/drawable-mdpi/stat_sys_upload_anim3.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_upload_anim4.png b/core/res/res/drawable-mdpi/stat_sys_upload_anim4.png
index a86d5cd..5349c30 100644
--- a/core/res/res/drawable-mdpi/stat_sys_upload_anim4.png
+++ b/core/res/res/drawable-mdpi/stat_sys_upload_anim4.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_upload_anim5.png b/core/res/res/drawable-mdpi/stat_sys_upload_anim5.png
index 3387dbb..b2f9996 100644
--- a/core/res/res/drawable-mdpi/stat_sys_upload_anim5.png
+++ b/core/res/res/drawable-mdpi/stat_sys_upload_anim5.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_vp_phone_call.png b/core/res/res/drawable-mdpi/stat_sys_vp_phone_call.png
index 32b23ed..4caf940 100644
--- a/core/res/res/drawable-mdpi/stat_sys_vp_phone_call.png
+++ b/core/res/res/drawable-mdpi/stat_sys_vp_phone_call.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_vp_phone_call_on_hold.png b/core/res/res/drawable-mdpi/stat_sys_vp_phone_call_on_hold.png
index a4c1fc8..e8ef51f 100644
--- a/core/res/res/drawable-mdpi/stat_sys_vp_phone_call_on_hold.png
+++ b/core/res/res/drawable-mdpi/stat_sys_vp_phone_call_on_hold.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_warning.png b/core/res/res/drawable-mdpi/stat_sys_warning.png
index 168f8f6..4e71377 100644
--- a/core/res/res/drawable-mdpi/stat_sys_warning.png
+++ b/core/res/res/drawable-mdpi/stat_sys_warning.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/status_bar_background.png b/core/res/res/drawable-mdpi/status_bar_background.png
index cd11166..db7b00b 100644
--- a/core/res/res/drawable-mdpi/status_bar_background.png
+++ b/core/res/res/drawable-mdpi/status_bar_background.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/status_bar_header_background.9.png b/core/res/res/drawable-mdpi/status_bar_header_background.9.png
index fa9a90c..eaa5082 100644
--- a/core/res/res/drawable-mdpi/status_bar_header_background.9.png
+++ b/core/res/res/drawable-mdpi/status_bar_header_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/status_bar_item_app_background_normal.9.png b/core/res/res/drawable-mdpi/status_bar_item_app_background_normal.9.png
index 873c556..0bdb3ce 100644
--- a/core/res/res/drawable-mdpi/status_bar_item_app_background_normal.9.png
+++ b/core/res/res/drawable-mdpi/status_bar_item_app_background_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/status_bar_item_background_focus.9.png b/core/res/res/drawable-mdpi/status_bar_item_background_focus.9.png
index c3e24158..6416956 100644
--- a/core/res/res/drawable-mdpi/status_bar_item_background_focus.9.png
+++ b/core/res/res/drawable-mdpi/status_bar_item_background_focus.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/status_bar_item_background_normal.9.png b/core/res/res/drawable-mdpi/status_bar_item_background_normal.9.png
index f0e4d06..f502fd9 100644
--- a/core/res/res/drawable-mdpi/status_bar_item_background_normal.9.png
+++ b/core/res/res/drawable-mdpi/status_bar_item_background_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/status_bar_item_background_pressed.9.png b/core/res/res/drawable-mdpi/status_bar_item_background_pressed.9.png
index 02b4e9a..cb4ea64 100644
--- a/core/res/res/drawable-mdpi/status_bar_item_background_pressed.9.png
+++ b/core/res/res/drawable-mdpi/status_bar_item_background_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/statusbar_background.9.png b/core/res/res/drawable-mdpi/statusbar_background.9.png
index eb7c1a4..7d68690 100644
--- a/core/res/res/drawable-mdpi/statusbar_background.9.png
+++ b/core/res/res/drawable-mdpi/statusbar_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/submenu_arrow_nofocus.png b/core/res/res/drawable-mdpi/submenu_arrow_nofocus.png
index cead09e..f0f4b08 100644
--- a/core/res/res/drawable-mdpi/submenu_arrow_nofocus.png
+++ b/core/res/res/drawable-mdpi/submenu_arrow_nofocus.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/switch_bg_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/switch_bg_disabled_holo_dark.9.png
index 76ccb8e..2ec3284 100644
--- a/core/res/res/drawable-mdpi/switch_bg_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/switch_bg_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/switch_bg_disabled_holo_light.9.png b/core/res/res/drawable-mdpi/switch_bg_disabled_holo_light.9.png
index 1e56c32..8dd2117 100644
--- a/core/res/res/drawable-mdpi/switch_bg_disabled_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/switch_bg_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/switch_bg_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/switch_bg_focused_holo_dark.9.png
index 914e433..af81459 100644
--- a/core/res/res/drawable-mdpi/switch_bg_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/switch_bg_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/switch_bg_focused_holo_light.9.png b/core/res/res/drawable-mdpi/switch_bg_focused_holo_light.9.png
index 89b0273..3af704f 100644
--- a/core/res/res/drawable-mdpi/switch_bg_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/switch_bg_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/switch_bg_holo_dark.9.png b/core/res/res/drawable-mdpi/switch_bg_holo_dark.9.png
index b5582b5..94d262bb 100644
--- a/core/res/res/drawable-mdpi/switch_bg_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/switch_bg_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/switch_bg_holo_light.9.png b/core/res/res/drawable-mdpi/switch_bg_holo_light.9.png
index a2af2b5..5375a5b 100644
--- a/core/res/res/drawable-mdpi/switch_bg_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/switch_bg_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/switch_thumb_activated_holo_dark.9.png b/core/res/res/drawable-mdpi/switch_thumb_activated_holo_dark.9.png
index 3d7c236..be0b2eee 100644
--- a/core/res/res/drawable-mdpi/switch_thumb_activated_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/switch_thumb_activated_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/switch_thumb_activated_holo_light.9.png b/core/res/res/drawable-mdpi/switch_thumb_activated_holo_light.9.png
index 3d7c236..be0b2eee 100644
--- a/core/res/res/drawable-mdpi/switch_thumb_activated_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/switch_thumb_activated_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/switch_thumb_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/switch_thumb_disabled_holo_dark.9.png
index 82f05d6..20c2f9a 100644
--- a/core/res/res/drawable-mdpi/switch_thumb_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/switch_thumb_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/switch_thumb_disabled_holo_light.9.png b/core/res/res/drawable-mdpi/switch_thumb_disabled_holo_light.9.png
index 82f05d6..20c2f9a 100644
--- a/core/res/res/drawable-mdpi/switch_thumb_disabled_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/switch_thumb_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/switch_thumb_holo_dark.9.png b/core/res/res/drawable-mdpi/switch_thumb_holo_dark.9.png
index 9bc7a68..7d0f3f5 100644
--- a/core/res/res/drawable-mdpi/switch_thumb_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/switch_thumb_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/switch_thumb_holo_light.9.png b/core/res/res/drawable-mdpi/switch_thumb_holo_light.9.png
index 9bc7a68..7d0f3f5 100644
--- a/core/res/res/drawable-mdpi/switch_thumb_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/switch_thumb_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/switch_thumb_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/switch_thumb_pressed_holo_dark.9.png
index f9f2fc6..29a2d2e 100644
--- a/core/res/res/drawable-mdpi/switch_thumb_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/switch_thumb_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/switch_thumb_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/switch_thumb_pressed_holo_light.9.png
index 28a57a2..9503508 100644
--- a/core/res/res/drawable-mdpi/switch_thumb_pressed_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/switch_thumb_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_action_add.png b/core/res/res/drawable-mdpi/sym_action_add.png
index af637b3..d179b6e 100644
--- a/core/res/res/drawable-mdpi/sym_action_add.png
+++ b/core/res/res/drawable-mdpi/sym_action_add.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_action_call.png b/core/res/res/drawable-mdpi/sym_action_call.png
index a442758..4b1383e 100644
--- a/core/res/res/drawable-mdpi/sym_action_call.png
+++ b/core/res/res/drawable-mdpi/sym_action_call.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_action_chat.png b/core/res/res/drawable-mdpi/sym_action_chat.png
index 0e28a7d..7f71f44 100644
--- a/core/res/res/drawable-mdpi/sym_action_chat.png
+++ b/core/res/res/drawable-mdpi/sym_action_chat.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_action_email.png b/core/res/res/drawable-mdpi/sym_action_email.png
index 5fea417..6aeed77 100644
--- a/core/res/res/drawable-mdpi/sym_action_email.png
+++ b/core/res/res/drawable-mdpi/sym_action_email.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_call_incoming.png b/core/res/res/drawable-mdpi/sym_call_incoming.png
index 652b882..84a61a1 100644
--- a/core/res/res/drawable-mdpi/sym_call_incoming.png
+++ b/core/res/res/drawable-mdpi/sym_call_incoming.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_call_missed.png b/core/res/res/drawable-mdpi/sym_call_missed.png
index ed859d0..a35bd47 100644
--- a/core/res/res/drawable-mdpi/sym_call_missed.png
+++ b/core/res/res/drawable-mdpi/sym_call_missed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_call_outgoing.png b/core/res/res/drawable-mdpi/sym_call_outgoing.png
index bdf675d..b43aade 100644
--- a/core/res/res/drawable-mdpi/sym_call_outgoing.png
+++ b/core/res/res/drawable-mdpi/sym_call_outgoing.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_contact_card.png b/core/res/res/drawable-mdpi/sym_contact_card.png
index 023ea6f..1f4f57f 100644
--- a/core/res/res/drawable-mdpi/sym_contact_card.png
+++ b/core/res/res/drawable-mdpi/sym_contact_card.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_delete.png b/core/res/res/drawable-mdpi/sym_keyboard_delete.png
index 74b836a..2d108b2 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_delete.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_delete.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_delete_dim.png b/core/res/res/drawable-mdpi/sym_keyboard_delete_dim.png
index 25460d8..b76065c2f 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_delete_dim.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_delete_dim.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_delete_holo.png b/core/res/res/drawable-mdpi/sym_keyboard_delete_holo.png
index 1555791..98cdd72 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_delete_holo.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_delete_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_enter.png b/core/res/res/drawable-mdpi/sym_keyboard_enter.png
index 0fa53ac..ea62bec 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_enter.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_enter.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_feedback_delete.png b/core/res/res/drawable-mdpi/sym_keyboard_feedback_delete.png
index 1edb10b..3932c18 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_feedback_delete.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_feedback_delete.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_feedback_ok.png b/core/res/res/drawable-mdpi/sym_keyboard_feedback_ok.png
index 3148836..5f87af3 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_feedback_ok.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_feedback_ok.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_feedback_return.png b/core/res/res/drawable-mdpi/sym_keyboard_feedback_return.png
index 03d9c9b..981a0a2 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_feedback_return.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_feedback_return.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_feedback_shift.png b/core/res/res/drawable-mdpi/sym_keyboard_feedback_shift.png
index 97f4661..008dc47 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_feedback_shift.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_feedback_shift.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_feedback_shift_locked.png b/core/res/res/drawable-mdpi/sym_keyboard_feedback_shift_locked.png
index 7194b30..c45c767 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_feedback_shift_locked.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_feedback_shift_locked.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_feedback_space.png b/core/res/res/drawable-mdpi/sym_keyboard_feedback_space.png
index 739db68..bac2909 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_feedback_space.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_feedback_space.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_num0_no_plus.png b/core/res/res/drawable-mdpi/sym_keyboard_num0_no_plus.png
index 9fefaea..ec56017 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_num0_no_plus.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_num0_no_plus.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_num1.png b/core/res/res/drawable-mdpi/sym_keyboard_num1.png
index 1f37e32..e57088d 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_num1.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_num1.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_num2.png b/core/res/res/drawable-mdpi/sym_keyboard_num2.png
index f899f78..00f07f3 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_num2.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_num2.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_num3.png b/core/res/res/drawable-mdpi/sym_keyboard_num3.png
index 6a0f5ef..69675151 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_num3.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_num3.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_num4.png b/core/res/res/drawable-mdpi/sym_keyboard_num4.png
index 3a25bcd..a1a6d77 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_num4.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_num4.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_num5.png b/core/res/res/drawable-mdpi/sym_keyboard_num5.png
index 064d4bf..9426776b 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_num5.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_num5.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_num6.png b/core/res/res/drawable-mdpi/sym_keyboard_num6.png
index 61ee0a6..e895c20 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_num6.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_num6.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_num7.png b/core/res/res/drawable-mdpi/sym_keyboard_num7.png
index b931d7b..72432a2 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_num7.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_num7.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_num8.png b/core/res/res/drawable-mdpi/sym_keyboard_num8.png
index f8d2891..9cf4d8b 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_num8.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_num8.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_num9.png b/core/res/res/drawable-mdpi/sym_keyboard_num9.png
index 056d067..fb4f6cb 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_num9.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_num9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_ok.png b/core/res/res/drawable-mdpi/sym_keyboard_ok.png
index b8b5292..22dda27 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_ok.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_ok.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_ok_dim.png b/core/res/res/drawable-mdpi/sym_keyboard_ok_dim.png
index 33ecff5..c0a627a 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_ok_dim.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_ok_dim.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_return.png b/core/res/res/drawable-mdpi/sym_keyboard_return.png
index 17f2574..115f3f4 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_return.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_return.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_shift.png b/core/res/res/drawable-mdpi/sym_keyboard_shift.png
index 572c1c1..9b6364a 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_shift.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_shift.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_shift_locked.png b/core/res/res/drawable-mdpi/sym_keyboard_shift_locked.png
index 175ed6d..7bed8bc 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_shift_locked.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_shift_locked.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_keyboard_space.png b/core/res/res/drawable-mdpi/sym_keyboard_space.png
index 4e6273b..f79b87e 100644
--- a/core/res/res/drawable-mdpi/sym_keyboard_space.png
+++ b/core/res/res/drawable-mdpi/sym_keyboard_space.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_bottom_holo.9.png b/core/res/res/drawable-mdpi/tab_bottom_holo.9.png
index 1e40b9c..fc66b0d 100644
--- a/core/res/res/drawable-mdpi/tab_bottom_holo.9.png
+++ b/core/res/res/drawable-mdpi/tab_bottom_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_focus.9.png b/core/res/res/drawable-mdpi/tab_focus.9.png
index d9bcc57a..3b0a41b 100644
--- a/core/res/res/drawable-mdpi/tab_focus.9.png
+++ b/core/res/res/drawable-mdpi/tab_focus.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_focus_bar_left.9.png b/core/res/res/drawable-mdpi/tab_focus_bar_left.9.png
index 2536d94..5a24257 100644
--- a/core/res/res/drawable-mdpi/tab_focus_bar_left.9.png
+++ b/core/res/res/drawable-mdpi/tab_focus_bar_left.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_focus_bar_right.9.png b/core/res/res/drawable-mdpi/tab_focus_bar_right.9.png
index 2536d94..5a24257 100644
--- a/core/res/res/drawable-mdpi/tab_focus_bar_right.9.png
+++ b/core/res/res/drawable-mdpi/tab_focus_bar_right.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_indicator_mtrl_alpha.9.png b/core/res/res/drawable-mdpi/tab_indicator_mtrl_alpha.9.png
index b69529c..ebd1b7e 100644
--- a/core/res/res/drawable-mdpi/tab_indicator_mtrl_alpha.9.png
+++ b/core/res/res/drawable-mdpi/tab_indicator_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_press.9.png b/core/res/res/drawable-mdpi/tab_press.9.png
index 3332660..eaf26a0 100644
--- a/core/res/res/drawable-mdpi/tab_press.9.png
+++ b/core/res/res/drawable-mdpi/tab_press.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_press_bar_left.9.png b/core/res/res/drawable-mdpi/tab_press_bar_left.9.png
index d2c75e3..b4c9a29 100644
--- a/core/res/res/drawable-mdpi/tab_press_bar_left.9.png
+++ b/core/res/res/drawable-mdpi/tab_press_bar_left.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_press_bar_right.9.png b/core/res/res/drawable-mdpi/tab_press_bar_right.9.png
index d2c75e3..b4c9a29 100644
--- a/core/res/res/drawable-mdpi/tab_press_bar_right.9.png
+++ b/core/res/res/drawable-mdpi/tab_press_bar_right.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_pressed_holo.9.png b/core/res/res/drawable-mdpi/tab_pressed_holo.9.png
index a76fbae..1e68ade 100644
--- a/core/res/res/drawable-mdpi/tab_pressed_holo.9.png
+++ b/core/res/res/drawable-mdpi/tab_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_selected.9.png b/core/res/res/drawable-mdpi/tab_selected.9.png
index 54190ea..3cbc871 100644
--- a/core/res/res/drawable-mdpi/tab_selected.9.png
+++ b/core/res/res/drawable-mdpi/tab_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_selected_bar_left.9.png b/core/res/res/drawable-mdpi/tab_selected_bar_left.9.png
index d20f3a2..2e9d41e 100644
--- a/core/res/res/drawable-mdpi/tab_selected_bar_left.9.png
+++ b/core/res/res/drawable-mdpi/tab_selected_bar_left.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_selected_bar_left_v4.9.png b/core/res/res/drawable-mdpi/tab_selected_bar_left_v4.9.png
index 6710945..1f8b350 100644
--- a/core/res/res/drawable-mdpi/tab_selected_bar_left_v4.9.png
+++ b/core/res/res/drawable-mdpi/tab_selected_bar_left_v4.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_selected_bar_right.9.png b/core/res/res/drawable-mdpi/tab_selected_bar_right.9.png
index d20f3a2..2e9d41e 100644
--- a/core/res/res/drawable-mdpi/tab_selected_bar_right.9.png
+++ b/core/res/res/drawable-mdpi/tab_selected_bar_right.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_selected_bar_right_v4.9.png b/core/res/res/drawable-mdpi/tab_selected_bar_right_v4.9.png
index 6710945..1f8b350 100644
--- a/core/res/res/drawable-mdpi/tab_selected_bar_right_v4.9.png
+++ b/core/res/res/drawable-mdpi/tab_selected_bar_right_v4.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_selected_focused_holo.9.png b/core/res/res/drawable-mdpi/tab_selected_focused_holo.9.png
index c9972e7..62f5d15 100644
--- a/core/res/res/drawable-mdpi/tab_selected_focused_holo.9.png
+++ b/core/res/res/drawable-mdpi/tab_selected_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_selected_holo.9.png b/core/res/res/drawable-mdpi/tab_selected_holo.9.png
index 587337c..4246d0b 100644
--- a/core/res/res/drawable-mdpi/tab_selected_holo.9.png
+++ b/core/res/res/drawable-mdpi/tab_selected_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_selected_pressed_holo.9.png b/core/res/res/drawable-mdpi/tab_selected_pressed_holo.9.png
index c98f046..7b20e5b 100644
--- a/core/res/res/drawable-mdpi/tab_selected_pressed_holo.9.png
+++ b/core/res/res/drawable-mdpi/tab_selected_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_selected_v4.9.png b/core/res/res/drawable-mdpi/tab_selected_v4.9.png
index e8e112a..805cdc5 100644
--- a/core/res/res/drawable-mdpi/tab_selected_v4.9.png
+++ b/core/res/res/drawable-mdpi/tab_selected_v4.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_unselected.9.png b/core/res/res/drawable-mdpi/tab_unselected.9.png
index 1b8a69c9..d6095f5 100644
--- a/core/res/res/drawable-mdpi/tab_unselected.9.png
+++ b/core/res/res/drawable-mdpi/tab_unselected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_unselected_focused_holo.9.png b/core/res/res/drawable-mdpi/tab_unselected_focused_holo.9.png
index f0cecd1..3816d64 100644
--- a/core/res/res/drawable-mdpi/tab_unselected_focused_holo.9.png
+++ b/core/res/res/drawable-mdpi/tab_unselected_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_unselected_holo.9.png b/core/res/res/drawable-mdpi/tab_unselected_holo.9.png
index a2dbf42..05dca9a 100644
--- a/core/res/res/drawable-mdpi/tab_unselected_holo.9.png
+++ b/core/res/res/drawable-mdpi/tab_unselected_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_unselected_pressed_holo.9.png b/core/res/res/drawable-mdpi/tab_unselected_pressed_holo.9.png
index 8753459..11d4506 100644
--- a/core/res/res/drawable-mdpi/tab_unselected_pressed_holo.9.png
+++ b/core/res/res/drawable-mdpi/tab_unselected_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_unselected_v4.9.png b/core/res/res/drawable-mdpi/tab_unselected_v4.9.png
index 229f503..c721a3d 100644
--- a/core/res/res/drawable-mdpi/tab_unselected_v4.9.png
+++ b/core/res/res/drawable-mdpi/tab_unselected_v4.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_edit_paste_window.9.png b/core/res/res/drawable-mdpi/text_edit_paste_window.9.png
index caacb5a..d27700c 100644
--- a/core/res/res/drawable-mdpi/text_edit_paste_window.9.png
+++ b/core/res/res/drawable-mdpi/text_edit_paste_window.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_edit_side_paste_window.9.png b/core/res/res/drawable-mdpi/text_edit_side_paste_window.9.png
index 04300d4..7363c4b 100644
--- a/core/res/res/drawable-mdpi/text_edit_side_paste_window.9.png
+++ b/core/res/res/drawable-mdpi/text_edit_side_paste_window.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_edit_suggestions_window.9.png b/core/res/res/drawable-mdpi/text_edit_suggestions_window.9.png
index caacb5a..d27700c 100644
--- a/core/res/res/drawable-mdpi/text_edit_suggestions_window.9.png
+++ b/core/res/res/drawable-mdpi/text_edit_suggestions_window.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_select_handle_left_mtrl_alpha.png b/core/res/res/drawable-mdpi/text_select_handle_left_mtrl_alpha.png
index 775f1bb..5684b52 100644
--- a/core/res/res/drawable-mdpi/text_select_handle_left_mtrl_alpha.png
+++ b/core/res/res/drawable-mdpi/text_select_handle_left_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_select_handle_middle_mtrl_alpha.png b/core/res/res/drawable-mdpi/text_select_handle_middle_mtrl_alpha.png
index e54d32e..160119c 100644
--- a/core/res/res/drawable-mdpi/text_select_handle_middle_mtrl_alpha.png
+++ b/core/res/res/drawable-mdpi/text_select_handle_middle_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_select_handle_right_mtrl_alpha.png b/core/res/res/drawable-mdpi/text_select_handle_right_mtrl_alpha.png
index 68fd053..0097e89 100644
--- a/core/res/res/drawable-mdpi/text_select_handle_right_mtrl_alpha.png
+++ b/core/res/res/drawable-mdpi/text_select_handle_right_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_activated_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_activated_holo_dark.9.png
index 33f798d..fd435ac 100644
--- a/core/res/res/drawable-mdpi/textfield_activated_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_activated_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_activated_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_activated_holo_light.9.png
index 622c684..fd435ac 100644
--- a/core/res/res/drawable-mdpi/textfield_activated_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/textfield_activated_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_activated_mtrl_alpha.9.png b/core/res/res/drawable-mdpi/textfield_activated_mtrl_alpha.9.png
index 45db6f7..60b2869 100644
--- a/core/res/res/drawable-mdpi/textfield_activated_mtrl_alpha.9.png
+++ b/core/res/res/drawable-mdpi/textfield_activated_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_bg_activated_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_bg_activated_holo_dark.9.png
index a233b0d..b5946e1 100644
--- a/core/res/res/drawable-mdpi/textfield_bg_activated_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_bg_activated_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_bg_default_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_bg_default_holo_dark.9.png
index 403f502..77adfe7 100644
--- a/core/res/res/drawable-mdpi/textfield_bg_default_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_bg_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_bg_disabled_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_bg_disabled_focused_holo_dark.9.png
index 0ded801..aad40c9 100644
--- a/core/res/res/drawable-mdpi/textfield_bg_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_bg_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_bg_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_bg_disabled_holo_dark.9.png
index 27237b8..685e1d6 100644
--- a/core/res/res/drawable-mdpi/textfield_bg_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_bg_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_bg_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_bg_focused_holo_dark.9.png
index 0e451f1..07c7620 100644
--- a/core/res/res/drawable-mdpi/textfield_bg_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_bg_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_default.9.png b/core/res/res/drawable-mdpi/textfield_default.9.png
index 1a59bb2..4d288b8 100644
--- a/core/res/res/drawable-mdpi/textfield_default.9.png
+++ b/core/res/res/drawable-mdpi/textfield_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_default_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_default_holo_dark.9.png
index 82fea5e..86b4c14 100644
--- a/core/res/res/drawable-mdpi/textfield_default_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_default_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_default_holo_light.9.png
index c780d7d..3ac07f6 100644
--- a/core/res/res/drawable-mdpi/textfield_default_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/textfield_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_default_mtrl_alpha.9.png b/core/res/res/drawable-mdpi/textfield_default_mtrl_alpha.9.png
index 8111fcb..e322399 100644
--- a/core/res/res/drawable-mdpi/textfield_default_mtrl_alpha.9.png
+++ b/core/res/res/drawable-mdpi/textfield_default_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_disabled.9.png b/core/res/res/drawable-mdpi/textfield_disabled.9.png
index 800205a..8e892b5 100644
--- a/core/res/res/drawable-mdpi/textfield_disabled.9.png
+++ b/core/res/res/drawable-mdpi/textfield_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_disabled_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_disabled_focused_holo_dark.9.png
index 24bdf71..4eb1f39 100644
--- a/core/res/res/drawable-mdpi/textfield_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_disabled_focused_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_disabled_focused_holo_light.9.png
index 0d5ea83..7bc1cdf 100644
--- a/core/res/res/drawable-mdpi/textfield_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/textfield_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_disabled_holo_dark.9.png
index 709f5ef..4a75449 100644
--- a/core/res/res/drawable-mdpi/textfield_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_disabled_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_disabled_holo_light.9.png
index ea6d2f7..6e51739 100644
--- a/core/res/res/drawable-mdpi/textfield_disabled_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/textfield_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_disabled_selected.9.png b/core/res/res/drawable-mdpi/textfield_disabled_selected.9.png
index 59e1536..46e7ecc 100644
--- a/core/res/res/drawable-mdpi/textfield_disabled_selected.9.png
+++ b/core/res/res/drawable-mdpi/textfield_disabled_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_focused_holo_dark.9.png
index 2d8dd23..6f288a5 100644
--- a/core/res/res/drawable-mdpi/textfield_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_focused_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_focused_holo_light.9.png
index 2d8dd23..6f288a5 100644
--- a/core/res/res/drawable-mdpi/textfield_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/textfield_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_longpress_holo.9.png b/core/res/res/drawable-mdpi/textfield_longpress_holo.9.png
index 2993b44..32b1444 100644
--- a/core/res/res/drawable-mdpi/textfield_longpress_holo.9.png
+++ b/core/res/res/drawable-mdpi/textfield_longpress_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_multiline_activated_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_multiline_activated_holo_dark.9.png
index 371d6e9..fd435ac 100644
--- a/core/res/res/drawable-mdpi/textfield_multiline_activated_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_multiline_activated_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_multiline_activated_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_multiline_activated_holo_light.9.png
index 225317f..fd435ac 100644
--- a/core/res/res/drawable-mdpi/textfield_multiline_activated_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/textfield_multiline_activated_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_multiline_default_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_multiline_default_holo_dark.9.png
index 4bd6f9f..86b4c14 100644
--- a/core/res/res/drawable-mdpi/textfield_multiline_default_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_multiline_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_multiline_default_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_multiline_default_holo_light.9.png
index 4b837b0..3ac07f6 100644
--- a/core/res/res/drawable-mdpi/textfield_multiline_default_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/textfield_multiline_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_multiline_disabled_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_multiline_disabled_focused_holo_dark.9.png
index 51cf919..4eb1f39 100644
--- a/core/res/res/drawable-mdpi/textfield_multiline_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_multiline_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_multiline_disabled_focused_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_multiline_disabled_focused_holo_light.9.png
index af8d7e1..7bc1cdf 100644
--- a/core/res/res/drawable-mdpi/textfield_multiline_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/textfield_multiline_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_multiline_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_multiline_disabled_holo_dark.9.png
index d0fb869..4a75449 100644
--- a/core/res/res/drawable-mdpi/textfield_multiline_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_multiline_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_multiline_disabled_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_multiline_disabled_holo_light.9.png
index a0e233e..6e51739 100644
--- a/core/res/res/drawable-mdpi/textfield_multiline_disabled_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/textfield_multiline_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_multiline_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_multiline_focused_holo_dark.9.png
index 2ed4985..aacb5ef 100644
--- a/core/res/res/drawable-mdpi/textfield_multiline_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_multiline_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_multiline_focused_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_multiline_focused_holo_light.9.png
index 0603348..aacb5ef 100644
--- a/core/res/res/drawable-mdpi/textfield_multiline_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/textfield_multiline_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_pressed_holo.9.png b/core/res/res/drawable-mdpi/textfield_pressed_holo.9.png
index 4aad237..22d9d92 100644
--- a/core/res/res/drawable-mdpi/textfield_pressed_holo.9.png
+++ b/core/res/res/drawable-mdpi/textfield_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_activated_mtrl_alpha.9.png b/core/res/res/drawable-mdpi/textfield_search_activated_mtrl_alpha.9.png
index d7faacf..2e5649f 100644
--- a/core/res/res/drawable-mdpi/textfield_search_activated_mtrl_alpha.9.png
+++ b/core/res/res/drawable-mdpi/textfield_search_activated_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_default.9.png b/core/res/res/drawable-mdpi/textfield_search_default.9.png
index 7dc5b27..134e15f 100644
--- a/core/res/res/drawable-mdpi/textfield_search_default.9.png
+++ b/core/res/res/drawable-mdpi/textfield_search_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_default_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_search_default_holo_dark.9.png
index 081657e..41d1690 100644
--- a/core/res/res/drawable-mdpi/textfield_search_default_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_search_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_default_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_search_default_holo_light.9.png
index 3f312b4..b633ea9 100644
--- a/core/res/res/drawable-mdpi/textfield_search_default_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/textfield_search_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_default_mtrl_alpha.9.png b/core/res/res/drawable-mdpi/textfield_search_default_mtrl_alpha.9.png
index 0a36039..045a413 100644
--- a/core/res/res/drawable-mdpi/textfield_search_default_mtrl_alpha.9.png
+++ b/core/res/res/drawable-mdpi/textfield_search_default_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_empty_default.9.png b/core/res/res/drawable-mdpi/textfield_search_empty_default.9.png
index 515117f..1fbf642 100644
--- a/core/res/res/drawable-mdpi/textfield_search_empty_default.9.png
+++ b/core/res/res/drawable-mdpi/textfield_search_empty_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_empty_pressed.9.png b/core/res/res/drawable-mdpi/textfield_search_empty_pressed.9.png
index a01f763..ec38d9c 100644
--- a/core/res/res/drawable-mdpi/textfield_search_empty_pressed.9.png
+++ b/core/res/res/drawable-mdpi/textfield_search_empty_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_empty_selected.9.png b/core/res/res/drawable-mdpi/textfield_search_empty_selected.9.png
index 611276f..af50f04 100644
--- a/core/res/res/drawable-mdpi/textfield_search_empty_selected.9.png
+++ b/core/res/res/drawable-mdpi/textfield_search_empty_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_pressed.9.png b/core/res/res/drawable-mdpi/textfield_search_pressed.9.png
index da00c25..f70fdf9 100644
--- a/core/res/res/drawable-mdpi/textfield_search_pressed.9.png
+++ b/core/res/res/drawable-mdpi/textfield_search_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_right_default_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_search_right_default_holo_dark.9.png
index b086fae..8370724 100644
--- a/core/res/res/drawable-mdpi/textfield_search_right_default_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_search_right_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_right_default_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_search_right_default_holo_light.9.png
index 73c336a..e2e61a8 100644
--- a/core/res/res/drawable-mdpi/textfield_search_right_default_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/textfield_search_right_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_selected.9.png b/core/res/res/drawable-mdpi/textfield_search_selected.9.png
index a9fd3b2..e175737 100644
--- a/core/res/res/drawable-mdpi/textfield_search_selected.9.png
+++ b/core/res/res/drawable-mdpi/textfield_search_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_selected.9.png b/core/res/res/drawable-mdpi/textfield_selected.9.png
index faadace..01ebc2e 100644
--- a/core/res/res/drawable-mdpi/textfield_selected.9.png
+++ b/core/res/res/drawable-mdpi/textfield_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/title_bar_medium.9.png b/core/res/res/drawable-mdpi/title_bar_medium.9.png
index 2d41d02..88f64c7 100644
--- a/core/res/res/drawable-mdpi/title_bar_medium.9.png
+++ b/core/res/res/drawable-mdpi/title_bar_medium.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/title_bar_portrait.9.png b/core/res/res/drawable-mdpi/title_bar_portrait.9.png
index 13b18d8..9e96e35 100644
--- a/core/res/res/drawable-mdpi/title_bar_portrait.9.png
+++ b/core/res/res/drawable-mdpi/title_bar_portrait.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/title_bar_tall.9.png b/core/res/res/drawable-mdpi/title_bar_tall.9.png
index 5a050c4..54d46bf4 100644
--- a/core/res/res/drawable-mdpi/title_bar_tall.9.png
+++ b/core/res/res/drawable-mdpi/title_bar_tall.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/transportcontrol_bg.9.png b/core/res/res/drawable-mdpi/transportcontrol_bg.9.png
index d5a339f..cd404a4 100644
--- a/core/res/res/drawable-mdpi/transportcontrol_bg.9.png
+++ b/core/res/res/drawable-mdpi/transportcontrol_bg.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/unknown_image.png b/core/res/res/drawable-mdpi/unknown_image.png
index b1c3e92..9162637 100644
--- a/core/res/res/drawable-mdpi/unknown_image.png
+++ b/core/res/res/drawable-mdpi/unknown_image.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/zoom_plate.9.png b/core/res/res/drawable-mdpi/zoom_plate.9.png
index c8c1a08..2a49f45 100644
--- a/core/res/res/drawable-mdpi/zoom_plate.9.png
+++ b/core/res/res/drawable-mdpi/zoom_plate.9.png
Binary files differ
diff --git a/core/res/res/drawable-nodpi/blank_tile.png b/core/res/res/drawable-nodpi/blank_tile.png
index 63b9296..b9f74e1 100644
--- a/core/res/res/drawable-nodpi/blank_tile.png
+++ b/core/res/res/drawable-nodpi/blank_tile.png
Binary files differ
diff --git a/core/res/res/drawable-nodpi/default_wallpaper.png b/core/res/res/drawable-nodpi/default_wallpaper.png
index a23f553..f366ce6 100644
--- a/core/res/res/drawable-nodpi/default_wallpaper.png
+++ b/core/res/res/drawable-nodpi/default_wallpaper.png
Binary files differ
diff --git a/core/res/res/drawable-nodpi/loading_tile.png b/core/res/res/drawable-nodpi/loading_tile.png
index f5a80c9..76cd211 100644
--- a/core/res/res/drawable-nodpi/loading_tile.png
+++ b/core/res/res/drawable-nodpi/loading_tile.png
Binary files differ
diff --git a/core/res/res/drawable-nodpi/loading_tile_android.png b/core/res/res/drawable-nodpi/loading_tile_android.png
index 8fde46f..0d19d7b 100644
--- a/core/res/res/drawable-nodpi/loading_tile_android.png
+++ b/core/res/res/drawable-nodpi/loading_tile_android.png
Binary files differ
diff --git a/core/res/res/drawable-nodpi/no_tile_128.png b/core/res/res/drawable-nodpi/no_tile_128.png
index a9b007d..44b5022 100644
--- a/core/res/res/drawable-nodpi/no_tile_128.png
+++ b/core/res/res/drawable-nodpi/no_tile_128.png
Binary files differ
diff --git a/core/res/res/drawable-nodpi/no_tile_256.png b/core/res/res/drawable-nodpi/no_tile_256.png
index 388234e..9f3df0f 100644
--- a/core/res/res/drawable-nodpi/no_tile_256.png
+++ b/core/res/res/drawable-nodpi/no_tile_256.png
Binary files differ
diff --git a/core/res/res/drawable-nodpi/text_cursor_holo_dark.9.png b/core/res/res/drawable-nodpi/text_cursor_holo_dark.9.png
index a1bddc3..7a364c5 100644
--- a/core/res/res/drawable-nodpi/text_cursor_holo_dark.9.png
+++ b/core/res/res/drawable-nodpi/text_cursor_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-nodpi/text_cursor_holo_light.9.png b/core/res/res/drawable-nodpi/text_cursor_holo_light.9.png
index cfdb849..638f8df 100644
--- a/core/res/res/drawable-nodpi/text_cursor_holo_light.9.png
+++ b/core/res/res/drawable-nodpi/text_cursor_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-sw600dp-hdpi/ic_lockscreen_handle_pressed.png b/core/res/res/drawable-sw600dp-hdpi/ic_lockscreen_handle_pressed.png
index 728fc67..8214682 100644
--- a/core/res/res/drawable-sw600dp-hdpi/ic_lockscreen_handle_pressed.png
+++ b/core/res/res/drawable-sw600dp-hdpi/ic_lockscreen_handle_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-sw600dp-hdpi/sym_keyboard_return_holo.png b/core/res/res/drawable-sw600dp-hdpi/sym_keyboard_return_holo.png
index f1bcf48..c577ecd 100644
--- a/core/res/res/drawable-sw600dp-hdpi/sym_keyboard_return_holo.png
+++ b/core/res/res/drawable-sw600dp-hdpi/sym_keyboard_return_holo.png
Binary files differ
diff --git a/core/res/res/drawable-sw600dp-hdpi/unlock_default.png b/core/res/res/drawable-sw600dp-hdpi/unlock_default.png
index 4adf674b..9bdbe2c 100644
--- a/core/res/res/drawable-sw600dp-hdpi/unlock_default.png
+++ b/core/res/res/drawable-sw600dp-hdpi/unlock_default.png
Binary files differ
diff --git a/core/res/res/drawable-sw600dp-hdpi/unlock_halo.png b/core/res/res/drawable-sw600dp-hdpi/unlock_halo.png
index 2a3f9df..a11de98 100644
--- a/core/res/res/drawable-sw600dp-hdpi/unlock_halo.png
+++ b/core/res/res/drawable-sw600dp-hdpi/unlock_halo.png
Binary files differ
diff --git a/core/res/res/drawable-sw600dp-hdpi/unlock_ring.png b/core/res/res/drawable-sw600dp-hdpi/unlock_ring.png
index 7d8a413..790d181 100644
--- a/core/res/res/drawable-sw600dp-hdpi/unlock_ring.png
+++ b/core/res/res/drawable-sw600dp-hdpi/unlock_ring.png
Binary files differ
diff --git a/core/res/res/drawable-sw600dp-hdpi/unlock_wave.png b/core/res/res/drawable-sw600dp-hdpi/unlock_wave.png
index d259499..4bbd947 100644
--- a/core/res/res/drawable-sw600dp-hdpi/unlock_wave.png
+++ b/core/res/res/drawable-sw600dp-hdpi/unlock_wave.png
Binary files differ
diff --git a/core/res/res/drawable-sw600dp-mdpi/ic_lockscreen_handle_pressed.png b/core/res/res/drawable-sw600dp-mdpi/ic_lockscreen_handle_pressed.png
index c7da024..b0df7a7 100644
--- a/core/res/res/drawable-sw600dp-mdpi/ic_lockscreen_handle_pressed.png
+++ b/core/res/res/drawable-sw600dp-mdpi/ic_lockscreen_handle_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-sw600dp-mdpi/sym_keyboard_return_holo.png b/core/res/res/drawable-sw600dp-mdpi/sym_keyboard_return_holo.png
index d5a7708..56d1194 100644
--- a/core/res/res/drawable-sw600dp-mdpi/sym_keyboard_return_holo.png
+++ b/core/res/res/drawable-sw600dp-mdpi/sym_keyboard_return_holo.png
Binary files differ
diff --git a/core/res/res/drawable-sw600dp-mdpi/unlock_default.png b/core/res/res/drawable-sw600dp-mdpi/unlock_default.png
index 9247467..c791caa 100644
--- a/core/res/res/drawable-sw600dp-mdpi/unlock_default.png
+++ b/core/res/res/drawable-sw600dp-mdpi/unlock_default.png
Binary files differ
diff --git a/core/res/res/drawable-sw600dp-mdpi/unlock_halo.png b/core/res/res/drawable-sw600dp-mdpi/unlock_halo.png
index df7826d..0d5ae76 100644
--- a/core/res/res/drawable-sw600dp-mdpi/unlock_halo.png
+++ b/core/res/res/drawable-sw600dp-mdpi/unlock_halo.png
Binary files differ
diff --git a/core/res/res/drawable-sw600dp-mdpi/unlock_ring.png b/core/res/res/drawable-sw600dp-mdpi/unlock_ring.png
index 3a2e6c6..5c8151f 100644
--- a/core/res/res/drawable-sw600dp-mdpi/unlock_ring.png
+++ b/core/res/res/drawable-sw600dp-mdpi/unlock_ring.png
Binary files differ
diff --git a/core/res/res/drawable-sw600dp-mdpi/unlock_wave.png b/core/res/res/drawable-sw600dp-mdpi/unlock_wave.png
index 9e38499..c2d471c 100644
--- a/core/res/res/drawable-sw600dp-mdpi/unlock_wave.png
+++ b/core/res/res/drawable-sw600dp-mdpi/unlock_wave.png
Binary files differ
diff --git a/core/res/res/drawable-sw600dp-nodpi/default_wallpaper.png b/core/res/res/drawable-sw600dp-nodpi/default_wallpaper.png
index 1e272e0..ec6d12c 100644
--- a/core/res/res/drawable-sw600dp-nodpi/default_wallpaper.png
+++ b/core/res/res/drawable-sw600dp-nodpi/default_wallpaper.png
Binary files differ
diff --git a/core/res/res/drawable-sw600dp-xhdpi/ic_lockscreen_handle_pressed.png b/core/res/res/drawable-sw600dp-xhdpi/ic_lockscreen_handle_pressed.png
index 534c10b..7511d95 100644
--- a/core/res/res/drawable-sw600dp-xhdpi/ic_lockscreen_handle_pressed.png
+++ b/core/res/res/drawable-sw600dp-xhdpi/ic_lockscreen_handle_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-sw600dp-xhdpi/sym_keyboard_return_holo.png b/core/res/res/drawable-sw600dp-xhdpi/sym_keyboard_return_holo.png
index 55174e0..378b1a6 100644
--- a/core/res/res/drawable-sw600dp-xhdpi/sym_keyboard_return_holo.png
+++ b/core/res/res/drawable-sw600dp-xhdpi/sym_keyboard_return_holo.png
Binary files differ
diff --git a/core/res/res/drawable-sw600dp-xhdpi/unlock_default.png b/core/res/res/drawable-sw600dp-xhdpi/unlock_default.png
index 4b837ef..df92e43d 100644
--- a/core/res/res/drawable-sw600dp-xhdpi/unlock_default.png
+++ b/core/res/res/drawable-sw600dp-xhdpi/unlock_default.png
Binary files differ
diff --git a/core/res/res/drawable-sw600dp-xhdpi/unlock_halo.png b/core/res/res/drawable-sw600dp-xhdpi/unlock_halo.png
index 187c6aa..2d841a4 100644
--- a/core/res/res/drawable-sw600dp-xhdpi/unlock_halo.png
+++ b/core/res/res/drawable-sw600dp-xhdpi/unlock_halo.png
Binary files differ
diff --git a/core/res/res/drawable-sw600dp-xhdpi/unlock_ring.png b/core/res/res/drawable-sw600dp-xhdpi/unlock_ring.png
index bdae414..cfd1b67 100644
--- a/core/res/res/drawable-sw600dp-xhdpi/unlock_ring.png
+++ b/core/res/res/drawable-sw600dp-xhdpi/unlock_ring.png
Binary files differ
diff --git a/core/res/res/drawable-sw600dp-xhdpi/unlock_wave.png b/core/res/res/drawable-sw600dp-xhdpi/unlock_wave.png
index 035bd92..cbaf8a5 100644
--- a/core/res/res/drawable-sw600dp-xhdpi/unlock_wave.png
+++ b/core/res/res/drawable-sw600dp-xhdpi/unlock_wave.png
Binary files differ
diff --git a/core/res/res/drawable-sw720dp-nodpi/default_wallpaper.png b/core/res/res/drawable-sw720dp-nodpi/default_wallpaper.png
index d10c77d..8fc95ec 100644
--- a/core/res/res/drawable-sw720dp-nodpi/default_wallpaper.png
+++ b/core/res/res/drawable-sw720dp-nodpi/default_wallpaper.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_bottom_solid_dark_holo.9.png b/core/res/res/drawable-xhdpi/ab_bottom_solid_dark_holo.9.png
index 5753346..43cc229 100644
--- a/core/res/res/drawable-xhdpi/ab_bottom_solid_dark_holo.9.png
+++ b/core/res/res/drawable-xhdpi/ab_bottom_solid_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_bottom_solid_inverse_holo.9.png b/core/res/res/drawable-xhdpi/ab_bottom_solid_inverse_holo.9.png
index 7e6c047..adc84bf 100644
--- a/core/res/res/drawable-xhdpi/ab_bottom_solid_inverse_holo.9.png
+++ b/core/res/res/drawable-xhdpi/ab_bottom_solid_inverse_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_bottom_solid_light_holo.9.png b/core/res/res/drawable-xhdpi/ab_bottom_solid_light_holo.9.png
index 8155fe8..01a2cb4 100644
--- a/core/res/res/drawable-xhdpi/ab_bottom_solid_light_holo.9.png
+++ b/core/res/res/drawable-xhdpi/ab_bottom_solid_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_bottom_transparent_dark_holo.9.png b/core/res/res/drawable-xhdpi/ab_bottom_transparent_dark_holo.9.png
index 6cee9a1..f353b39 100644
--- a/core/res/res/drawable-xhdpi/ab_bottom_transparent_dark_holo.9.png
+++ b/core/res/res/drawable-xhdpi/ab_bottom_transparent_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_bottom_transparent_light_holo.9.png b/core/res/res/drawable-xhdpi/ab_bottom_transparent_light_holo.9.png
index fa4d76a..ee16aca 100644
--- a/core/res/res/drawable-xhdpi/ab_bottom_transparent_light_holo.9.png
+++ b/core/res/res/drawable-xhdpi/ab_bottom_transparent_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_share_pack_holo_dark.9.png b/core/res/res/drawable-xhdpi/ab_share_pack_holo_dark.9.png
index 55099d49..a8652f5 100644
--- a/core/res/res/drawable-xhdpi/ab_share_pack_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/ab_share_pack_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_share_pack_holo_light.9.png b/core/res/res/drawable-xhdpi/ab_share_pack_holo_light.9.png
index 3c4701f..8c2b6e8 100644
--- a/core/res/res/drawable-xhdpi/ab_share_pack_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/ab_share_pack_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_share_pack_mtrl_alpha.9.png b/core/res/res/drawable-xhdpi/ab_share_pack_mtrl_alpha.9.png
index 8337ffe..83c3e90 100644
--- a/core/res/res/drawable-xhdpi/ab_share_pack_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xhdpi/ab_share_pack_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_solid_dark_holo.9.png b/core/res/res/drawable-xhdpi/ab_solid_dark_holo.9.png
index 6622cba..94813b3 100644
--- a/core/res/res/drawable-xhdpi/ab_solid_dark_holo.9.png
+++ b/core/res/res/drawable-xhdpi/ab_solid_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_solid_light_holo.9.png b/core/res/res/drawable-xhdpi/ab_solid_light_holo.9.png
index c427297..aed6a6d 100644
--- a/core/res/res/drawable-xhdpi/ab_solid_light_holo.9.png
+++ b/core/res/res/drawable-xhdpi/ab_solid_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_solid_shadow_holo.9.png b/core/res/res/drawable-xhdpi/ab_solid_shadow_holo.9.png
index d0df29d..eeec62c 100644
--- a/core/res/res/drawable-xhdpi/ab_solid_shadow_holo.9.png
+++ b/core/res/res/drawable-xhdpi/ab_solid_shadow_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_solid_shadow_mtrl_alpha.9.png b/core/res/res/drawable-xhdpi/ab_solid_shadow_mtrl_alpha.9.png
index f51af63..52c36a0 100644
--- a/core/res/res/drawable-xhdpi/ab_solid_shadow_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xhdpi/ab_solid_shadow_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_stacked_solid_dark_holo.9.png b/core/res/res/drawable-xhdpi/ab_stacked_solid_dark_holo.9.png
index a0d9c1b9..7c60c7e 100644
--- a/core/res/res/drawable-xhdpi/ab_stacked_solid_dark_holo.9.png
+++ b/core/res/res/drawable-xhdpi/ab_stacked_solid_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_stacked_solid_inverse_holo.9.png b/core/res/res/drawable-xhdpi/ab_stacked_solid_inverse_holo.9.png
index 16b9bef..e02d3ff 100644
--- a/core/res/res/drawable-xhdpi/ab_stacked_solid_inverse_holo.9.png
+++ b/core/res/res/drawable-xhdpi/ab_stacked_solid_inverse_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_stacked_solid_light_holo.9.png b/core/res/res/drawable-xhdpi/ab_stacked_solid_light_holo.9.png
index d36f99f..66a134a 100644
--- a/core/res/res/drawable-xhdpi/ab_stacked_solid_light_holo.9.png
+++ b/core/res/res/drawable-xhdpi/ab_stacked_solid_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_stacked_transparent_dark_holo.9.png b/core/res/res/drawable-xhdpi/ab_stacked_transparent_dark_holo.9.png
index 5ad475d..9b821e2 100644
--- a/core/res/res/drawable-xhdpi/ab_stacked_transparent_dark_holo.9.png
+++ b/core/res/res/drawable-xhdpi/ab_stacked_transparent_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_stacked_transparent_light_holo.9.png b/core/res/res/drawable-xhdpi/ab_stacked_transparent_light_holo.9.png
index 6ade5ee..19db24b 100644
--- a/core/res/res/drawable-xhdpi/ab_stacked_transparent_light_holo.9.png
+++ b/core/res/res/drawable-xhdpi/ab_stacked_transparent_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_transparent_dark_holo.9.png b/core/res/res/drawable-xhdpi/ab_transparent_dark_holo.9.png
index 719b923..d127ee2 100644
--- a/core/res/res/drawable-xhdpi/ab_transparent_dark_holo.9.png
+++ b/core/res/res/drawable-xhdpi/ab_transparent_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_transparent_light_holo.9.png b/core/res/res/drawable-xhdpi/ab_transparent_light_holo.9.png
index 6da264d..baa4550 100644
--- a/core/res/res/drawable-xhdpi/ab_transparent_light_holo.9.png
+++ b/core/res/res/drawable-xhdpi/ab_transparent_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/activity_title_bar.9.png b/core/res/res/drawable-xhdpi/activity_title_bar.9.png
index 949f31e..cf9a194 100644
--- a/core/res/res/drawable-xhdpi/activity_title_bar.9.png
+++ b/core/res/res/drawable-xhdpi/activity_title_bar.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/arrow_down_float.png b/core/res/res/drawable-xhdpi/arrow_down_float.png
index b165ee3..8c8c740 100644
--- a/core/res/res/drawable-xhdpi/arrow_down_float.png
+++ b/core/res/res/drawable-xhdpi/arrow_down_float.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/arrow_up_float.png b/core/res/res/drawable-xhdpi/arrow_up_float.png
index 793ec42..8f91a7e 100644
--- a/core/res/res/drawable-xhdpi/arrow_up_float.png
+++ b/core/res/res/drawable-xhdpi/arrow_up_float.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/battery_charge_background.png b/core/res/res/drawable-xhdpi/battery_charge_background.png
index 84b168c..d2e6f2a 100644
--- a/core/res/res/drawable-xhdpi/battery_charge_background.png
+++ b/core/res/res/drawable-xhdpi/battery_charge_background.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/bottom_bar.png b/core/res/res/drawable-xhdpi/bottom_bar.png
index 67b1e47..884a286 100644
--- a/core/res/res/drawable-xhdpi/bottom_bar.png
+++ b/core/res/res/drawable-xhdpi/bottom_bar.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_cab_done_default_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_cab_done_default_holo_dark.9.png
index 7ef2db7..2a56e60 100644
--- a/core/res/res/drawable-xhdpi/btn_cab_done_default_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_cab_done_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_cab_done_default_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_cab_done_default_holo_light.9.png
index 2283b4c..21e2b90 100644
--- a/core/res/res/drawable-xhdpi/btn_cab_done_default_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_cab_done_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_cab_done_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_cab_done_focused_holo_dark.9.png
index 6d2039e..eb9ea06 100644
--- a/core/res/res/drawable-xhdpi/btn_cab_done_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_cab_done_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_cab_done_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_cab_done_focused_holo_light.9.png
index 3c909b5..ac52bf0 100644
--- a/core/res/res/drawable-xhdpi/btn_cab_done_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_cab_done_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_cab_done_pressed_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_cab_done_pressed_holo_dark.9.png
index d89d5c7..1340de7 100644
--- a/core/res/res/drawable-xhdpi/btn_cab_done_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_cab_done_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_cab_done_pressed_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_cab_done_pressed_holo_light.9.png
index 0146156..ef546c7 100644
--- a/core/res/res/drawable-xhdpi/btn_cab_done_pressed_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_cab_done_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_buttonless_off.png b/core/res/res/drawable-xhdpi/btn_check_buttonless_off.png
index 243a976..1841f51 100644
--- a/core/res/res/drawable-xhdpi/btn_check_buttonless_off.png
+++ b/core/res/res/drawable-xhdpi/btn_check_buttonless_off.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_buttonless_on.png b/core/res/res/drawable-xhdpi/btn_check_buttonless_on.png
index 348a264..a120c8e 100644
--- a/core/res/res/drawable-xhdpi/btn_check_buttonless_on.png
+++ b/core/res/res/drawable-xhdpi/btn_check_buttonless_on.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_label_background.9.png b/core/res/res/drawable-xhdpi/btn_check_label_background.9.png
index 9257ca9..719b31d 100644
--- a/core/res/res/drawable-xhdpi/btn_check_label_background.9.png
+++ b/core/res/res/drawable-xhdpi/btn_check_label_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off.png b/core/res/res/drawable-xhdpi/btn_check_off.png
index 933864b..c2fe5da 100644
--- a/core/res/res/drawable-xhdpi/btn_check_off.png
+++ b/core/res/res/drawable-xhdpi/btn_check_off.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_disable.png b/core/res/res/drawable-xhdpi/btn_check_off_disable.png
index 926c694..04cfbb1 100644
--- a/core/res/res/drawable-xhdpi/btn_check_off_disable.png
+++ b/core/res/res/drawable-xhdpi/btn_check_off_disable.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_disable_focused.png b/core/res/res/drawable-xhdpi/btn_check_off_disable_focused.png
index 9e99fbd..c6cb440 100644
--- a/core/res/res/drawable-xhdpi/btn_check_off_disable_focused.png
+++ b/core/res/res/drawable-xhdpi/btn_check_off_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_disable_focused_holo_dark.png b/core/res/res/drawable-xhdpi/btn_check_off_disable_focused_holo_dark.png
index 8417bfe..382b9e3 100644
--- a/core/res/res/drawable-xhdpi/btn_check_off_disable_focused_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_check_off_disable_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_disable_focused_holo_light.png b/core/res/res/drawable-xhdpi/btn_check_off_disable_focused_holo_light.png
index 903bf20..dfe265b 100644
--- a/core/res/res/drawable-xhdpi/btn_check_off_disable_focused_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_check_off_disable_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_disable_holo_dark.png b/core/res/res/drawable-xhdpi/btn_check_off_disable_holo_dark.png
index 8417bfe..382b9e3 100644
--- a/core/res/res/drawable-xhdpi/btn_check_off_disable_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_check_off_disable_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_disable_holo_light.png b/core/res/res/drawable-xhdpi/btn_check_off_disable_holo_light.png
index 903bf20..dfe265b 100644
--- a/core/res/res/drawable-xhdpi/btn_check_off_disable_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_check_off_disable_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_disabled_focused_holo_dark.png b/core/res/res/drawable-xhdpi/btn_check_off_disabled_focused_holo_dark.png
index 1dd1eec..50cc68e 100644
--- a/core/res/res/drawable-xhdpi/btn_check_off_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_check_off_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_disabled_focused_holo_light.png b/core/res/res/drawable-xhdpi/btn_check_off_disabled_focused_holo_light.png
index 481eb77..6f4d22a 100644
--- a/core/res/res/drawable-xhdpi/btn_check_off_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_check_off_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_disabled_holo_dark.png b/core/res/res/drawable-xhdpi/btn_check_off_disabled_holo_dark.png
index 85ab478..6080a4a 100644
--- a/core/res/res/drawable-xhdpi/btn_check_off_disabled_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_check_off_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_disabled_holo_light.png b/core/res/res/drawable-xhdpi/btn_check_off_disabled_holo_light.png
index 6a364bb..a1cf8b8 100644
--- a/core/res/res/drawable-xhdpi/btn_check_off_disabled_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_check_off_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_focused_holo_dark.png b/core/res/res/drawable-xhdpi/btn_check_off_focused_holo_dark.png
index 828e4bc..87a9148 100644
--- a/core/res/res/drawable-xhdpi/btn_check_off_focused_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_check_off_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_focused_holo_light.png b/core/res/res/drawable-xhdpi/btn_check_off_focused_holo_light.png
index 1c5e503..d5bad99 100644
--- a/core/res/res/drawable-xhdpi/btn_check_off_focused_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_check_off_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_holo.png b/core/res/res/drawable-xhdpi/btn_check_off_holo.png
index bcedcea..eebf1ab 100644
--- a/core/res/res/drawable-xhdpi/btn_check_off_holo.png
+++ b/core/res/res/drawable-xhdpi/btn_check_off_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_holo_dark.png b/core/res/res/drawable-xhdpi/btn_check_off_holo_dark.png
index f696db0..208f552 100644
--- a/core/res/res/drawable-xhdpi/btn_check_off_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_check_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_holo_light.png b/core/res/res/drawable-xhdpi/btn_check_off_holo_light.png
index 4518328..bb0eb40 100644
--- a/core/res/res/drawable-xhdpi/btn_check_off_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_check_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_normal_holo_dark.png b/core/res/res/drawable-xhdpi/btn_check_off_normal_holo_dark.png
index d3d2fa4..10cc2e080 100644
--- a/core/res/res/drawable-xhdpi/btn_check_off_normal_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_check_off_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_normal_holo_light.png b/core/res/res/drawable-xhdpi/btn_check_off_normal_holo_light.png
index b7f226a..d488ce0 100644
--- a/core/res/res/drawable-xhdpi/btn_check_off_normal_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_check_off_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_pressed.png b/core/res/res/drawable-xhdpi/btn_check_off_pressed.png
index 3a79e75..798cf22 100644
--- a/core/res/res/drawable-xhdpi/btn_check_off_pressed.png
+++ b/core/res/res/drawable-xhdpi/btn_check_off_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_pressed_holo_dark.png b/core/res/res/drawable-xhdpi/btn_check_off_pressed_holo_dark.png
index ffb13b1..0770fa6 100644
--- a/core/res/res/drawable-xhdpi/btn_check_off_pressed_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_check_off_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_pressed_holo_light.png b/core/res/res/drawable-xhdpi/btn_check_off_pressed_holo_light.png
index 86eb889..3376e47 100644
--- a/core/res/res/drawable-xhdpi/btn_check_off_pressed_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_check_off_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_selected.png b/core/res/res/drawable-xhdpi/btn_check_off_selected.png
index 8004974..2507d6d 100644
--- a/core/res/res/drawable-xhdpi/btn_check_off_selected.png
+++ b/core/res/res/drawable-xhdpi/btn_check_off_selected.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_on.png b/core/res/res/drawable-xhdpi/btn_check_on.png
index 3c98740..10bcfc7 100644
--- a/core/res/res/drawable-xhdpi/btn_check_on.png
+++ b/core/res/res/drawable-xhdpi/btn_check_on.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_on_disable.png b/core/res/res/drawable-xhdpi/btn_check_on_disable.png
index 11917b5..5d16f64 100644
--- a/core/res/res/drawable-xhdpi/btn_check_on_disable.png
+++ b/core/res/res/drawable-xhdpi/btn_check_on_disable.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_on_disabled_focused_holo_dark.png b/core/res/res/drawable-xhdpi/btn_check_on_disabled_focused_holo_dark.png
index a42c7ff..e80dd23 100644
--- a/core/res/res/drawable-xhdpi/btn_check_on_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_check_on_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_on_disabled_focused_holo_light.png b/core/res/res/drawable-xhdpi/btn_check_on_disabled_focused_holo_light.png
index 74fa0ff..2d4707b 100644
--- a/core/res/res/drawable-xhdpi/btn_check_on_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_check_on_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_on_disabled_holo_dark.png b/core/res/res/drawable-xhdpi/btn_check_on_disabled_holo_dark.png
index 499147e..21649f3 100644
--- a/core/res/res/drawable-xhdpi/btn_check_on_disabled_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_check_on_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_on_disabled_holo_light.png b/core/res/res/drawable-xhdpi/btn_check_on_disabled_holo_light.png
index d705b42..775c859 100644
--- a/core/res/res/drawable-xhdpi/btn_check_on_disabled_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_check_on_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_on_focused_holo_dark.png b/core/res/res/drawable-xhdpi/btn_check_on_focused_holo_dark.png
index e64a188..df7273f 100644
--- a/core/res/res/drawable-xhdpi/btn_check_on_focused_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_check_on_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_on_focused_holo_light.png b/core/res/res/drawable-xhdpi/btn_check_on_focused_holo_light.png
index 697a18a..2bcefec 100644
--- a/core/res/res/drawable-xhdpi/btn_check_on_focused_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_check_on_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_on_holo.png b/core/res/res/drawable-xhdpi/btn_check_on_holo.png
index 65dd58d..69cfa74 100644
--- a/core/res/res/drawable-xhdpi/btn_check_on_holo.png
+++ b/core/res/res/drawable-xhdpi/btn_check_on_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_on_holo_dark.png b/core/res/res/drawable-xhdpi/btn_check_on_holo_dark.png
index 2fe7b01..d5f5a66 100644
--- a/core/res/res/drawable-xhdpi/btn_check_on_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_check_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_on_holo_light.png b/core/res/res/drawable-xhdpi/btn_check_on_holo_light.png
index a2612d7..b76d939 100644
--- a/core/res/res/drawable-xhdpi/btn_check_on_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_check_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_on_pressed.png b/core/res/res/drawable-xhdpi/btn_check_on_pressed.png
index 995775e..e1be7fc 100644
--- a/core/res/res/drawable-xhdpi/btn_check_on_pressed.png
+++ b/core/res/res/drawable-xhdpi/btn_check_on_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_dark.png b/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_dark.png
index 028eed6..7fe8f25 100644
--- a/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_light.png b/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_light.png
index 61efd3a..41e969c 100644
--- a/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_on_selected.png b/core/res/res/drawable-xhdpi/btn_check_on_selected.png
index a46f2f4..e05289c 100644
--- a/core/res/res/drawable-xhdpi/btn_check_on_selected.png
+++ b/core/res/res/drawable-xhdpi/btn_check_on_selected.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_circle_disable.png b/core/res/res/drawable-xhdpi/btn_circle_disable.png
index 420e01a..2daff1a 100644
--- a/core/res/res/drawable-xhdpi/btn_circle_disable.png
+++ b/core/res/res/drawable-xhdpi/btn_circle_disable.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_circle_disable_focused.png b/core/res/res/drawable-xhdpi/btn_circle_disable_focused.png
index 6876916..9bd29ef 100644
--- a/core/res/res/drawable-xhdpi/btn_circle_disable_focused.png
+++ b/core/res/res/drawable-xhdpi/btn_circle_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_circle_normal.png b/core/res/res/drawable-xhdpi/btn_circle_normal.png
index de7e71e..01e3f2f 100644
--- a/core/res/res/drawable-xhdpi/btn_circle_normal.png
+++ b/core/res/res/drawable-xhdpi/btn_circle_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_circle_pressed.png b/core/res/res/drawable-xhdpi/btn_circle_pressed.png
index 17776e4..b62a0b7 100644
--- a/core/res/res/drawable-xhdpi/btn_circle_pressed.png
+++ b/core/res/res/drawable-xhdpi/btn_circle_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_circle_selected.png b/core/res/res/drawable-xhdpi/btn_circle_selected.png
index 98aeff5..83fb7b0 100644
--- a/core/res/res/drawable-xhdpi/btn_circle_selected.png
+++ b/core/res/res/drawable-xhdpi/btn_circle_selected.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_close_normal.png b/core/res/res/drawable-xhdpi/btn_close_normal.png
index 2d0b0ea..320f04f 100644
--- a/core/res/res/drawable-xhdpi/btn_close_normal.png
+++ b/core/res/res/drawable-xhdpi/btn_close_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_close_pressed.png b/core/res/res/drawable-xhdpi/btn_close_pressed.png
index 5d9b5ee..c9f6003 100644
--- a/core/res/res/drawable-xhdpi/btn_close_pressed.png
+++ b/core/res/res/drawable-xhdpi/btn_close_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_close_selected.png b/core/res/res/drawable-xhdpi/btn_close_selected.png
index 1bf1740..3871aef 100644
--- a/core/res/res/drawable-xhdpi/btn_close_selected.png
+++ b/core/res/res/drawable-xhdpi/btn_close_selected.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_dark.9.png
index 41230fe..e1ec30e 100644
--- a/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_light.9.png
index 41230fe..e1ec30e 100644
--- a/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_disabled_holo.9.png b/core/res/res/drawable-xhdpi/btn_default_disabled_holo.9.png
index df2a621..0a7452e7 100644
--- a/core/res/res/drawable-xhdpi/btn_default_disabled_holo.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_disabled_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_disabled_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_default_disabled_holo_dark.9.png
index 9fa8682..3fc8753 100644
--- a/core/res/res/drawable-xhdpi/btn_default_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_disabled_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_default_disabled_holo_light.9.png
index 9fa8682..3fc8753 100644
--- a/core/res/res/drawable-xhdpi/btn_default_disabled_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_focused_holo.9.png b/core/res/res/drawable-xhdpi/btn_default_focused_holo.9.png
index 392cee4..670cdaf 100644
--- a/core/res/res/drawable-xhdpi/btn_default_focused_holo.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_default_focused_holo_dark.9.png
index 73488f3..c1c3dcd 100644
--- a/core/res/res/drawable-xhdpi/btn_default_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_default_focused_holo_light.9.png
index 73488f3..c1c3dcd 100644
--- a/core/res/res/drawable-xhdpi/btn_default_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_normal.9.png b/core/res/res/drawable-xhdpi/btn_default_normal.9.png
index 7080905..72eaa2c 100644
--- a/core/res/res/drawable-xhdpi/btn_default_normal.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_normal_disable.9.png b/core/res/res/drawable-xhdpi/btn_default_normal_disable.9.png
index 704bb55..7842fc9 100644
--- a/core/res/res/drawable-xhdpi/btn_default_normal_disable.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_normal_disable.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_normal_disable_focused.9.png b/core/res/res/drawable-xhdpi/btn_default_normal_disable_focused.9.png
index 7f64c75..6538a95 100644
--- a/core/res/res/drawable-xhdpi/btn_default_normal_disable_focused.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_normal_disable_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_normal_holo.9.png b/core/res/res/drawable-xhdpi/btn_default_normal_holo.9.png
index 92a49db..f1e7575 100644
--- a/core/res/res/drawable-xhdpi/btn_default_normal_holo.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_normal_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_default_normal_holo_dark.9.png
index 28edccd..b1dfc3ec 100644
--- a/core/res/res/drawable-xhdpi/btn_default_normal_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_normal_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_default_normal_holo_light.9.png
index 38f8c01..7c69622 100644
--- a/core/res/res/drawable-xhdpi/btn_default_normal_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_pressed.9.png b/core/res/res/drawable-xhdpi/btn_default_pressed.9.png
index 849cd48..88308cb 100644
--- a/core/res/res/drawable-xhdpi/btn_default_pressed.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_pressed_holo.9.png b/core/res/res/drawable-xhdpi/btn_default_pressed_holo.9.png
index 0544d32..bef82df 100644
--- a/core/res/res/drawable-xhdpi/btn_default_pressed_holo.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_pressed_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_default_pressed_holo_dark.9.png
index 37f30eb..1d45201 100644
--- a/core/res/res/drawable-xhdpi/btn_default_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_pressed_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_default_pressed_holo_light.9.png
index a4ac0c7..3edc0b7 100644
--- a/core/res/res/drawable-xhdpi/btn_default_pressed_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_selected.9.png b/core/res/res/drawable-xhdpi/btn_default_selected.9.png
index 2be8da6..5b737f2 100644
--- a/core/res/res/drawable-xhdpi/btn_default_selected.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_small_normal.9.png b/core/res/res/drawable-xhdpi/btn_default_small_normal.9.png
index 5b7a3bd..4e5d8a2 100644
--- a/core/res/res/drawable-xhdpi/btn_default_small_normal.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_small_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_small_normal_disable.9.png b/core/res/res/drawable-xhdpi/btn_default_small_normal_disable.9.png
index 36cbd3e..20db7f5 100644
--- a/core/res/res/drawable-xhdpi/btn_default_small_normal_disable.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_small_normal_disable.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_small_normal_disable_focused.9.png b/core/res/res/drawable-xhdpi/btn_default_small_normal_disable_focused.9.png
index 3ce0038..ca29825 100644
--- a/core/res/res/drawable-xhdpi/btn_default_small_normal_disable_focused.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_small_normal_disable_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_small_pressed.9.png b/core/res/res/drawable-xhdpi/btn_default_small_pressed.9.png
index 787ba9e..eb09640 100644
--- a/core/res/res/drawable-xhdpi/btn_default_small_pressed.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_small_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_small_selected.9.png b/core/res/res/drawable-xhdpi/btn_default_small_selected.9.png
index 5874b8c..d995a70 100644
--- a/core/res/res/drawable-xhdpi/btn_default_small_selected.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_small_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_transparent_normal.9.png b/core/res/res/drawable-xhdpi/btn_default_transparent_normal.9.png
index fb2fbf5..25cf7be 100644
--- a/core/res/res/drawable-xhdpi/btn_default_transparent_normal.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_transparent_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_dialog_disable.png b/core/res/res/drawable-xhdpi/btn_dialog_disable.png
index 571e40af..e299526 100644
--- a/core/res/res/drawable-xhdpi/btn_dialog_disable.png
+++ b/core/res/res/drawable-xhdpi/btn_dialog_disable.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_dialog_normal.png b/core/res/res/drawable-xhdpi/btn_dialog_normal.png
index 2d0b0ea..320f04f 100644
--- a/core/res/res/drawable-xhdpi/btn_dialog_normal.png
+++ b/core/res/res/drawable-xhdpi/btn_dialog_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_dialog_pressed.png b/core/res/res/drawable-xhdpi/btn_dialog_pressed.png
index 56195d2..bd5bcd2 100644
--- a/core/res/res/drawable-xhdpi/btn_dialog_pressed.png
+++ b/core/res/res/drawable-xhdpi/btn_dialog_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_dialog_selected.png b/core/res/res/drawable-xhdpi/btn_dialog_selected.png
index c33da56..552225c 100644
--- a/core/res/res/drawable-xhdpi/btn_dialog_selected.png
+++ b/core/res/res/drawable-xhdpi/btn_dialog_selected.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_dropdown_disabled.9.png b/core/res/res/drawable-xhdpi/btn_dropdown_disabled.9.png
index e45c731..3cef2c9 100644
--- a/core/res/res/drawable-xhdpi/btn_dropdown_disabled.9.png
+++ b/core/res/res/drawable-xhdpi/btn_dropdown_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_dropdown_disabled_focused.9.png b/core/res/res/drawable-xhdpi/btn_dropdown_disabled_focused.9.png
index 1e4cec3..b5c912e 100644
--- a/core/res/res/drawable-xhdpi/btn_dropdown_disabled_focused.9.png
+++ b/core/res/res/drawable-xhdpi/btn_dropdown_disabled_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_dropdown_normal.9.png b/core/res/res/drawable-xhdpi/btn_dropdown_normal.9.png
index aab7658..90d6ca3 100644
--- a/core/res/res/drawable-xhdpi/btn_dropdown_normal.9.png
+++ b/core/res/res/drawable-xhdpi/btn_dropdown_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_dropdown_pressed.9.png b/core/res/res/drawable-xhdpi/btn_dropdown_pressed.9.png
index 4a1ddf3..d3081a1 100644
--- a/core/res/res/drawable-xhdpi/btn_dropdown_pressed.9.png
+++ b/core/res/res/drawable-xhdpi/btn_dropdown_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_dropdown_selected.9.png b/core/res/res/drawable-xhdpi/btn_dropdown_selected.9.png
index cdae834..c2fc744 100644
--- a/core/res/res/drawable-xhdpi/btn_dropdown_selected.9.png
+++ b/core/res/res/drawable-xhdpi/btn_dropdown_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_erase_default.9.png b/core/res/res/drawable-xhdpi/btn_erase_default.9.png
index f189e9c..f1c2e0f 100644
--- a/core/res/res/drawable-xhdpi/btn_erase_default.9.png
+++ b/core/res/res/drawable-xhdpi/btn_erase_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_erase_pressed.9.png b/core/res/res/drawable-xhdpi/btn_erase_pressed.9.png
index 99cd6fd..34db5af 100644
--- a/core/res/res/drawable-xhdpi/btn_erase_pressed.9.png
+++ b/core/res/res/drawable-xhdpi/btn_erase_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_erase_selected.9.png b/core/res/res/drawable-xhdpi/btn_erase_selected.9.png
index b6de266..e602c31 100644
--- a/core/res/res/drawable-xhdpi/btn_erase_selected.9.png
+++ b/core/res/res/drawable-xhdpi/btn_erase_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_global_search_normal.9.png b/core/res/res/drawable-xhdpi/btn_global_search_normal.9.png
index cc11942..04fc3b1 100644
--- a/core/res/res/drawable-xhdpi/btn_global_search_normal.9.png
+++ b/core/res/res/drawable-xhdpi/btn_global_search_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_group_disabled_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_group_disabled_holo_dark.9.png
index 6bf2fb4..1eacefe 100644
--- a/core/res/res/drawable-xhdpi/btn_group_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_group_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_group_disabled_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_group_disabled_holo_light.9.png
index 979eccd..7adadc8 100644
--- a/core/res/res/drawable-xhdpi/btn_group_disabled_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_group_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_group_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_group_focused_holo_dark.9.png
index 7252482..f048af5 100644
--- a/core/res/res/drawable-xhdpi/btn_group_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_group_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_group_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_group_focused_holo_light.9.png
index 7252482..f048af5 100644
--- a/core/res/res/drawable-xhdpi/btn_group_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_group_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_group_normal_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_group_normal_holo_dark.9.png
index 3065564..6f72a46 100644
--- a/core/res/res/drawable-xhdpi/btn_group_normal_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_group_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_group_normal_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_group_normal_holo_light.9.png
index a444e63..749b6a2 100644
--- a/core/res/res/drawable-xhdpi/btn_group_normal_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_group_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_group_pressed_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_group_pressed_holo_dark.9.png
index 60d6675..575d60a 100644
--- a/core/res/res/drawable-xhdpi/btn_group_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_group_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_group_pressed_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_group_pressed_holo_light.9.png
index 142a1c9..fd07e62 100644
--- a/core/res/res/drawable-xhdpi/btn_group_pressed_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_group_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_normal_holo.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_normal_holo.9.png
index d2cd029..8455a85 100644
--- a/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_normal_holo.9.png
+++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_normal_off_holo.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_normal_off_holo.9.png
index 0f709eb..a15584b 100644
--- a/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_normal_off_holo.9.png
+++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_normal_off_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_normal_on_holo.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_normal_on_holo.9.png
index 2f4de8e..1e35be5 100644
--- a/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_normal_on_holo.9.png
+++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_normal_on_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_holo.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_holo.9.png
index 3871689e..76f39ea 100644
--- a/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_holo.9.png
+++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_off_holo.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_off_holo.9.png
index 836ea6e..c643c14 100644
--- a/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_off_holo.9.png
+++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_off_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on_holo.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on_holo.9.png
index 279db1f..63cdd04 100644
--- a/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on_holo.9.png
+++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_normal.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_normal.9.png
index 981cad9..b047934 100644
--- a/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_normal.9.png
+++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_normal_off.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_normal_off.9.png
index 2252293..a5a7188 100644
--- a/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_normal_off.9.png
+++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_normal_off.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_normal_on.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_normal_on.9.png
index 4db7078..061b6a4 100644
--- a/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_normal_on.9.png
+++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_normal_on.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_pressed.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_pressed.9.png
index 04e7ea1..44fa3c4 100644
--- a/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_pressed.9.png
+++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_pressed_off.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_pressed_off.9.png
index 95e91e8..e086d35 100644
--- a/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_pressed_off.9.png
+++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_pressed_off.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_pressed_on.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_pressed_on.9.png
index cdd47d5..39f2518 100644
--- a/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_pressed_on.9.png
+++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_fulltrans_pressed_on.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_light_normal_holo.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_light_normal_holo.9.png
index b26f1d2..18652f9 100644
--- a/core/res/res/drawable-xhdpi/btn_keyboard_key_light_normal_holo.9.png
+++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_light_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_light_pressed_holo.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_light_pressed_holo.9.png
index c23a4b2..7abe72d 100644
--- a/core/res/res/drawable-xhdpi/btn_keyboard_key_light_pressed_holo.9.png
+++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_light_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_normal.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_normal.9.png
index 1f3a6b3..c76a687 100644
--- a/core/res/res/drawable-xhdpi/btn_keyboard_key_normal.9.png
+++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_normal_off.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_normal_off.9.png
index 2a9b6f4..d74c64e 100644
--- a/core/res/res/drawable-xhdpi/btn_keyboard_key_normal_off.9.png
+++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_normal_off.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_normal_on.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_normal_on.9.png
index 096d6e9..8510bff 100644
--- a/core/res/res/drawable-xhdpi/btn_keyboard_key_normal_on.9.png
+++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_normal_on.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_pressed.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_pressed.9.png
index 20852d6..3a7e2dc 100644
--- a/core/res/res/drawable-xhdpi/btn_keyboard_key_pressed.9.png
+++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_pressed_off.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_pressed_off.9.png
index 271c6b4..17cfccd 100644
--- a/core/res/res/drawable-xhdpi/btn_keyboard_key_pressed_off.9.png
+++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_pressed_off.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_pressed_on.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_pressed_on.9.png
index e72ec79..5cf39e6 100644
--- a/core/res/res/drawable-xhdpi/btn_keyboard_key_pressed_on.9.png
+++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_pressed_on.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_normal.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_normal.9.png
index 200d934..7c05f86 100644
--- a/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_normal.9.png
+++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_normal_off.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_normal_off.9.png
index e08dcc5..d7b4a54 100644
--- a/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_normal_off.9.png
+++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_normal_off.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_normal_on.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_normal_on.9.png
index fd512d9c..1099471 100644
--- a/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_normal_on.9.png
+++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_normal_on.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_pressed.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_pressed.9.png
index f3626b6..b90d044 100644
--- a/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_pressed.9.png
+++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_pressed_off.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_pressed_off.9.png
index b18642d..0c19c09 100644
--- a/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_pressed_off.9.png
+++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_pressed_off.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_pressed_on.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_pressed_on.9.png
index 134c4a9..165fecc 100644
--- a/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_pressed_on.9.png
+++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_pressed_on.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_selected.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_selected.9.png
index 8dd3070..5dfdea1 100644
--- a/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_selected.9.png
+++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_trans_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_media_player.9.png b/core/res/res/drawable-xhdpi/btn_media_player.9.png
index 06e523d..46c6772 100644
--- a/core/res/res/drawable-xhdpi/btn_media_player.9.png
+++ b/core/res/res/drawable-xhdpi/btn_media_player.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_media_player_disabled.9.png b/core/res/res/drawable-xhdpi/btn_media_player_disabled.9.png
index 9b3350f..33e3257 100644
--- a/core/res/res/drawable-xhdpi/btn_media_player_disabled.9.png
+++ b/core/res/res/drawable-xhdpi/btn_media_player_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_media_player_disabled_selected.9.png b/core/res/res/drawable-xhdpi/btn_media_player_disabled_selected.9.png
index 1872a0b..f394081 100644
--- a/core/res/res/drawable-xhdpi/btn_media_player_disabled_selected.9.png
+++ b/core/res/res/drawable-xhdpi/btn_media_player_disabled_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_media_player_pressed.9.png b/core/res/res/drawable-xhdpi/btn_media_player_pressed.9.png
index e8810b0..a4dc5be 100644
--- a/core/res/res/drawable-xhdpi/btn_media_player_pressed.9.png
+++ b/core/res/res/drawable-xhdpi/btn_media_player_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_media_player_selected.9.png b/core/res/res/drawable-xhdpi/btn_media_player_selected.9.png
index b9287d6..cabb4c7a 100644
--- a/core/res/res/drawable-xhdpi/btn_media_player_selected.9.png
+++ b/core/res/res/drawable-xhdpi/btn_media_player_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_minus_default.png b/core/res/res/drawable-xhdpi/btn_minus_default.png
index 7e952f11..dd738d6 100644
--- a/core/res/res/drawable-xhdpi/btn_minus_default.png
+++ b/core/res/res/drawable-xhdpi/btn_minus_default.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_minus_disable.png b/core/res/res/drawable-xhdpi/btn_minus_disable.png
index 63901e3..7e5a7dba 100644
--- a/core/res/res/drawable-xhdpi/btn_minus_disable.png
+++ b/core/res/res/drawable-xhdpi/btn_minus_disable.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_minus_disable_focused.png b/core/res/res/drawable-xhdpi/btn_minus_disable_focused.png
index 9073d49..c25cdd4 100644
--- a/core/res/res/drawable-xhdpi/btn_minus_disable_focused.png
+++ b/core/res/res/drawable-xhdpi/btn_minus_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_minus_pressed.png b/core/res/res/drawable-xhdpi/btn_minus_pressed.png
index 49dfc3f..d9c96d8 100644
--- a/core/res/res/drawable-xhdpi/btn_minus_pressed.png
+++ b/core/res/res/drawable-xhdpi/btn_minus_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_minus_selected.png b/core/res/res/drawable-xhdpi/btn_minus_selected.png
index d1d2101..db21144 100644
--- a/core/res/res/drawable-xhdpi/btn_minus_selected.png
+++ b/core/res/res/drawable-xhdpi/btn_minus_selected.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_plus_default.png b/core/res/res/drawable-xhdpi/btn_plus_default.png
index d47113a..fe1f69b 100644
--- a/core/res/res/drawable-xhdpi/btn_plus_default.png
+++ b/core/res/res/drawable-xhdpi/btn_plus_default.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_plus_disable.png b/core/res/res/drawable-xhdpi/btn_plus_disable.png
index 6432c81..03fe8fc 100644
--- a/core/res/res/drawable-xhdpi/btn_plus_disable.png
+++ b/core/res/res/drawable-xhdpi/btn_plus_disable.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_plus_disable_focused.png b/core/res/res/drawable-xhdpi/btn_plus_disable_focused.png
index 666bf9d..e976295 100644
--- a/core/res/res/drawable-xhdpi/btn_plus_disable_focused.png
+++ b/core/res/res/drawable-xhdpi/btn_plus_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_plus_pressed.png b/core/res/res/drawable-xhdpi/btn_plus_pressed.png
index 2fdb1d2..a339e0c 100644
--- a/core/res/res/drawable-xhdpi/btn_plus_pressed.png
+++ b/core/res/res/drawable-xhdpi/btn_plus_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_plus_selected.png b/core/res/res/drawable-xhdpi/btn_plus_selected.png
index 0f9157d..61970a8 100644
--- a/core/res/res/drawable-xhdpi/btn_plus_selected.png
+++ b/core/res/res/drawable-xhdpi/btn_plus_selected.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_label_background.9.png b/core/res/res/drawable-xhdpi/btn_radio_label_background.9.png
index e5dee60..5b06d9e0 100644
--- a/core/res/res/drawable-xhdpi/btn_radio_label_background.9.png
+++ b/core/res/res/drawable-xhdpi/btn_radio_label_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_off.png b/core/res/res/drawable-xhdpi/btn_radio_off.png
index b25fd98..5ca9357 100644
--- a/core/res/res/drawable-xhdpi/btn_radio_off.png
+++ b/core/res/res/drawable-xhdpi/btn_radio_off.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_off_disabled_focused_holo_dark.png b/core/res/res/drawable-xhdpi/btn_radio_off_disabled_focused_holo_dark.png
index b93bb66..38cee96 100644
--- a/core/res/res/drawable-xhdpi/btn_radio_off_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_radio_off_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_off_disabled_focused_holo_light.png b/core/res/res/drawable-xhdpi/btn_radio_off_disabled_focused_holo_light.png
index 2625e8b..f17a377 100644
--- a/core/res/res/drawable-xhdpi/btn_radio_off_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_radio_off_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_off_disabled_holo_dark.png b/core/res/res/drawable-xhdpi/btn_radio_off_disabled_holo_dark.png
index aa5f830..b3eb085 100644
--- a/core/res/res/drawable-xhdpi/btn_radio_off_disabled_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_radio_off_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_off_disabled_holo_light.png b/core/res/res/drawable-xhdpi/btn_radio_off_disabled_holo_light.png
index 1030a80..f85b96a 100644
--- a/core/res/res/drawable-xhdpi/btn_radio_off_disabled_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_radio_off_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_off_focused_holo_dark.png b/core/res/res/drawable-xhdpi/btn_radio_off_focused_holo_dark.png
index 5a12961..21f3417 100644
--- a/core/res/res/drawable-xhdpi/btn_radio_off_focused_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_radio_off_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_off_focused_holo_light.png b/core/res/res/drawable-xhdpi/btn_radio_off_focused_holo_light.png
index 1e2108c..e903843 100644
--- a/core/res/res/drawable-xhdpi/btn_radio_off_focused_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_radio_off_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_off_holo.png b/core/res/res/drawable-xhdpi/btn_radio_off_holo.png
index 1866d07..c929b1d 100644
--- a/core/res/res/drawable-xhdpi/btn_radio_off_holo.png
+++ b/core/res/res/drawable-xhdpi/btn_radio_off_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_off_holo_dark.png b/core/res/res/drawable-xhdpi/btn_radio_off_holo_dark.png
index d04d6e5..ebacfa9 100644
--- a/core/res/res/drawable-xhdpi/btn_radio_off_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_radio_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_off_holo_light.png b/core/res/res/drawable-xhdpi/btn_radio_off_holo_light.png
index 36e82bb..0fdca1a 100644
--- a/core/res/res/drawable-xhdpi/btn_radio_off_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_radio_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_off_pressed.png b/core/res/res/drawable-xhdpi/btn_radio_off_pressed.png
index 1ee1d4c..368e909 100644
--- a/core/res/res/drawable-xhdpi/btn_radio_off_pressed.png
+++ b/core/res/res/drawable-xhdpi/btn_radio_off_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_off_pressed_holo_dark.png b/core/res/res/drawable-xhdpi/btn_radio_off_pressed_holo_dark.png
index 0f5f32f..0112b2e 100644
--- a/core/res/res/drawable-xhdpi/btn_radio_off_pressed_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_radio_off_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_off_pressed_holo_light.png b/core/res/res/drawable-xhdpi/btn_radio_off_pressed_holo_light.png
index 4097ef2..208053e 100644
--- a/core/res/res/drawable-xhdpi/btn_radio_off_pressed_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_radio_off_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_off_selected.png b/core/res/res/drawable-xhdpi/btn_radio_off_selected.png
index 2ef78f0..dcab5ce 100644
--- a/core/res/res/drawable-xhdpi/btn_radio_off_selected.png
+++ b/core/res/res/drawable-xhdpi/btn_radio_off_selected.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_on.png b/core/res/res/drawable-xhdpi/btn_radio_on.png
index c3b757e..45a993d 100644
--- a/core/res/res/drawable-xhdpi/btn_radio_on.png
+++ b/core/res/res/drawable-xhdpi/btn_radio_on.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_on_disabled_focused_holo_dark.png b/core/res/res/drawable-xhdpi/btn_radio_on_disabled_focused_holo_dark.png
index 97994e8..34d48d1 100644
--- a/core/res/res/drawable-xhdpi/btn_radio_on_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_radio_on_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_on_disabled_focused_holo_light.png b/core/res/res/drawable-xhdpi/btn_radio_on_disabled_focused_holo_light.png
index 67e9bd1..9bdd151 100644
--- a/core/res/res/drawable-xhdpi/btn_radio_on_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_radio_on_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_on_disabled_holo_dark.png b/core/res/res/drawable-xhdpi/btn_radio_on_disabled_holo_dark.png
index 346909d..3e71884 100644
--- a/core/res/res/drawable-xhdpi/btn_radio_on_disabled_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_radio_on_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_on_disabled_holo_light.png b/core/res/res/drawable-xhdpi/btn_radio_on_disabled_holo_light.png
index 5741490..c9376af 100644
--- a/core/res/res/drawable-xhdpi/btn_radio_on_disabled_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_radio_on_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_on_focused_holo_dark.png b/core/res/res/drawable-xhdpi/btn_radio_on_focused_holo_dark.png
index 587f0ce..1df7a2d7 100644
--- a/core/res/res/drawable-xhdpi/btn_radio_on_focused_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_radio_on_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_on_focused_holo_light.png b/core/res/res/drawable-xhdpi/btn_radio_on_focused_holo_light.png
index 6d78b97..a7ce3a2 100644
--- a/core/res/res/drawable-xhdpi/btn_radio_on_focused_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_radio_on_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_on_holo.png b/core/res/res/drawable-xhdpi/btn_radio_on_holo.png
index e14392f..c08c16b 100644
--- a/core/res/res/drawable-xhdpi/btn_radio_on_holo.png
+++ b/core/res/res/drawable-xhdpi/btn_radio_on_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_on_holo_dark.png b/core/res/res/drawable-xhdpi/btn_radio_on_holo_dark.png
index e565dfe..5283295 100644
--- a/core/res/res/drawable-xhdpi/btn_radio_on_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_radio_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_on_holo_light.png b/core/res/res/drawable-xhdpi/btn_radio_on_holo_light.png
index 5a7a5f7..70af942 100644
--- a/core/res/res/drawable-xhdpi/btn_radio_on_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_radio_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_on_mtrl_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_on_mtrl_alpha.png
index be4aaf3..c04fd9c 100644
--- a/core/res/res/drawable-xhdpi/btn_radio_on_mtrl_alpha.png
+++ b/core/res/res/drawable-xhdpi/btn_radio_on_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_on_pressed.png b/core/res/res/drawable-xhdpi/btn_radio_on_pressed.png
index a986746..97b1117 100644
--- a/core/res/res/drawable-xhdpi/btn_radio_on_pressed.png
+++ b/core/res/res/drawable-xhdpi/btn_radio_on_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_on_pressed_holo_dark.png b/core/res/res/drawable-xhdpi/btn_radio_on_pressed_holo_dark.png
index a3795a0..c529e50 100644
--- a/core/res/res/drawable-xhdpi/btn_radio_on_pressed_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_radio_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_on_pressed_holo_light.png b/core/res/res/drawable-xhdpi/btn_radio_on_pressed_holo_light.png
index f8e3bd4f8..1938f73 100644
--- a/core/res/res/drawable-xhdpi/btn_radio_on_pressed_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_radio_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_on_pressed_mtrl_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_on_pressed_mtrl_alpha.png
index a7ed0f8..55e4b80 100644
--- a/core/res/res/drawable-xhdpi/btn_radio_on_pressed_mtrl_alpha.png
+++ b/core/res/res/drawable-xhdpi/btn_radio_on_pressed_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_on_selected.png b/core/res/res/drawable-xhdpi/btn_radio_on_selected.png
index b3d4234..7de5399 100644
--- a/core/res/res/drawable-xhdpi/btn_radio_on_selected.png
+++ b/core/res/res/drawable-xhdpi/btn_radio_on_selected.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_rating_star_off_disabled_focused_holo_dark.png b/core/res/res/drawable-xhdpi/btn_rating_star_off_disabled_focused_holo_dark.png
index 94d6b6e..ea1787c 100644
--- a/core/res/res/drawable-xhdpi/btn_rating_star_off_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_rating_star_off_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_rating_star_off_disabled_focused_holo_light.png b/core/res/res/drawable-xhdpi/btn_rating_star_off_disabled_focused_holo_light.png
index 68b8e53..e3515bc 100644
--- a/core/res/res/drawable-xhdpi/btn_rating_star_off_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_rating_star_off_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_rating_star_off_disabled_holo_dark.png b/core/res/res/drawable-xhdpi/btn_rating_star_off_disabled_holo_dark.png
index 0968ae1..5cf5c9b 100644
--- a/core/res/res/drawable-xhdpi/btn_rating_star_off_disabled_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_rating_star_off_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_rating_star_off_disabled_holo_light.png b/core/res/res/drawable-xhdpi/btn_rating_star_off_disabled_holo_light.png
index a444bf3..64e36e6 100644
--- a/core/res/res/drawable-xhdpi/btn_rating_star_off_disabled_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_rating_star_off_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_rating_star_off_focused_holo_dark.png b/core/res/res/drawable-xhdpi/btn_rating_star_off_focused_holo_dark.png
index 95eee6a..c4a19da 100644
--- a/core/res/res/drawable-xhdpi/btn_rating_star_off_focused_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_rating_star_off_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_rating_star_off_focused_holo_light.png b/core/res/res/drawable-xhdpi/btn_rating_star_off_focused_holo_light.png
index 4489c67..2879625 100644
--- a/core/res/res/drawable-xhdpi/btn_rating_star_off_focused_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_rating_star_off_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_rating_star_off_mtrl_alpha.png b/core/res/res/drawable-xhdpi/btn_rating_star_off_mtrl_alpha.png
index 33ec44c..9cfd6a0 100644
--- a/core/res/res/drawable-xhdpi/btn_rating_star_off_mtrl_alpha.png
+++ b/core/res/res/drawable-xhdpi/btn_rating_star_off_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_rating_star_off_normal.png b/core/res/res/drawable-xhdpi/btn_rating_star_off_normal.png
index 67cbc1a..3cbb359 100644
--- a/core/res/res/drawable-xhdpi/btn_rating_star_off_normal.png
+++ b/core/res/res/drawable-xhdpi/btn_rating_star_off_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_rating_star_off_normal_holo_dark.png b/core/res/res/drawable-xhdpi/btn_rating_star_off_normal_holo_dark.png
index 0f46649..eecd5f3 100644
--- a/core/res/res/drawable-xhdpi/btn_rating_star_off_normal_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_rating_star_off_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_rating_star_off_normal_holo_light.png b/core/res/res/drawable-xhdpi/btn_rating_star_off_normal_holo_light.png
index e3c0761..3ccd8c1 100644
--- a/core/res/res/drawable-xhdpi/btn_rating_star_off_normal_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_rating_star_off_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_rating_star_off_pressed.png b/core/res/res/drawable-xhdpi/btn_rating_star_off_pressed.png
index aaa1c5b..1ab17f9 100644
--- a/core/res/res/drawable-xhdpi/btn_rating_star_off_pressed.png
+++ b/core/res/res/drawable-xhdpi/btn_rating_star_off_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_rating_star_off_pressed_holo_dark.png b/core/res/res/drawable-xhdpi/btn_rating_star_off_pressed_holo_dark.png
index dad564d..25df160 100644
--- a/core/res/res/drawable-xhdpi/btn_rating_star_off_pressed_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_rating_star_off_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_rating_star_off_pressed_holo_light.png b/core/res/res/drawable-xhdpi/btn_rating_star_off_pressed_holo_light.png
index c891ae3..5808a9e 100644
--- a/core/res/res/drawable-xhdpi/btn_rating_star_off_pressed_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_rating_star_off_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_rating_star_off_selected.png b/core/res/res/drawable-xhdpi/btn_rating_star_off_selected.png
index 7eed14c..116491b 100644
--- a/core/res/res/drawable-xhdpi/btn_rating_star_off_selected.png
+++ b/core/res/res/drawable-xhdpi/btn_rating_star_off_selected.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_rating_star_on_disabled_focused_holo_dark.png b/core/res/res/drawable-xhdpi/btn_rating_star_on_disabled_focused_holo_dark.png
index a8a7bf8..885a784 100644
--- a/core/res/res/drawable-xhdpi/btn_rating_star_on_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_rating_star_on_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_rating_star_on_disabled_focused_holo_light.png b/core/res/res/drawable-xhdpi/btn_rating_star_on_disabled_focused_holo_light.png
index e898819..1db8de6 100644
--- a/core/res/res/drawable-xhdpi/btn_rating_star_on_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_rating_star_on_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_rating_star_on_disabled_holo_dark.png b/core/res/res/drawable-xhdpi/btn_rating_star_on_disabled_holo_dark.png
index f3a9d3d..22b180f7 100644
--- a/core/res/res/drawable-xhdpi/btn_rating_star_on_disabled_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_rating_star_on_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_rating_star_on_disabled_holo_light.png b/core/res/res/drawable-xhdpi/btn_rating_star_on_disabled_holo_light.png
index 92dfd1a..ac064d5 100644
--- a/core/res/res/drawable-xhdpi/btn_rating_star_on_disabled_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_rating_star_on_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_rating_star_on_focused_holo_dark.png b/core/res/res/drawable-xhdpi/btn_rating_star_on_focused_holo_dark.png
index 0c9d726..7ef1534 100644
--- a/core/res/res/drawable-xhdpi/btn_rating_star_on_focused_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_rating_star_on_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_rating_star_on_focused_holo_light.png b/core/res/res/drawable-xhdpi/btn_rating_star_on_focused_holo_light.png
index 3b2055c..2d9da06 100644
--- a/core/res/res/drawable-xhdpi/btn_rating_star_on_focused_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_rating_star_on_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_rating_star_on_mtrl_alpha.png b/core/res/res/drawable-xhdpi/btn_rating_star_on_mtrl_alpha.png
index 0166d70..ab4a000 100644
--- a/core/res/res/drawable-xhdpi/btn_rating_star_on_mtrl_alpha.png
+++ b/core/res/res/drawable-xhdpi/btn_rating_star_on_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_rating_star_on_normal.png b/core/res/res/drawable-xhdpi/btn_rating_star_on_normal.png
index 1db48b3..f5ea54f 100644
--- a/core/res/res/drawable-xhdpi/btn_rating_star_on_normal.png
+++ b/core/res/res/drawable-xhdpi/btn_rating_star_on_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_rating_star_on_normal_holo_dark.png b/core/res/res/drawable-xhdpi/btn_rating_star_on_normal_holo_dark.png
index 2b9b617..812c752 100644
--- a/core/res/res/drawable-xhdpi/btn_rating_star_on_normal_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_rating_star_on_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_rating_star_on_normal_holo_light.png b/core/res/res/drawable-xhdpi/btn_rating_star_on_normal_holo_light.png
index 386b90a..d2a75b6 100644
--- a/core/res/res/drawable-xhdpi/btn_rating_star_on_normal_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_rating_star_on_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_rating_star_on_pressed.png b/core/res/res/drawable-xhdpi/btn_rating_star_on_pressed.png
index a8e5d00..e6349e4 100644
--- a/core/res/res/drawable-xhdpi/btn_rating_star_on_pressed.png
+++ b/core/res/res/drawable-xhdpi/btn_rating_star_on_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_rating_star_on_pressed_holo_dark.png b/core/res/res/drawable-xhdpi/btn_rating_star_on_pressed_holo_dark.png
index 530eed2..45e2f95 100644
--- a/core/res/res/drawable-xhdpi/btn_rating_star_on_pressed_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_rating_star_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_rating_star_on_pressed_holo_light.png b/core/res/res/drawable-xhdpi/btn_rating_star_on_pressed_holo_light.png
index 33ee629..27da6f2 100644
--- a/core/res/res/drawable-xhdpi/btn_rating_star_on_pressed_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_rating_star_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_rating_star_on_selected.png b/core/res/res/drawable-xhdpi/btn_rating_star_on_selected.png
index 8ec2103..dc240dc 100644
--- a/core/res/res/drawable-xhdpi/btn_rating_star_on_selected.png
+++ b/core/res/res/drawable-xhdpi/btn_rating_star_on_selected.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_search_dialog_default.9.png b/core/res/res/drawable-xhdpi/btn_search_dialog_default.9.png
index 0a12dc9..bd9d7e6 100644
--- a/core/res/res/drawable-xhdpi/btn_search_dialog_default.9.png
+++ b/core/res/res/drawable-xhdpi/btn_search_dialog_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_search_dialog_pressed.9.png b/core/res/res/drawable-xhdpi/btn_search_dialog_pressed.9.png
index 35ad67c..3b6e38e 100644
--- a/core/res/res/drawable-xhdpi/btn_search_dialog_pressed.9.png
+++ b/core/res/res/drawable-xhdpi/btn_search_dialog_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_search_dialog_selected.9.png b/core/res/res/drawable-xhdpi/btn_search_dialog_selected.9.png
index 2f9af47..308e734 100644
--- a/core/res/res/drawable-xhdpi/btn_search_dialog_selected.9.png
+++ b/core/res/res/drawable-xhdpi/btn_search_dialog_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_search_dialog_voice_default.9.png b/core/res/res/drawable-xhdpi/btn_search_dialog_voice_default.9.png
index d3c7709..6b16c523 100644
--- a/core/res/res/drawable-xhdpi/btn_search_dialog_voice_default.9.png
+++ b/core/res/res/drawable-xhdpi/btn_search_dialog_voice_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_search_dialog_voice_pressed.9.png b/core/res/res/drawable-xhdpi/btn_search_dialog_voice_pressed.9.png
index 0c4f0da..7d13024 100644
--- a/core/res/res/drawable-xhdpi/btn_search_dialog_voice_pressed.9.png
+++ b/core/res/res/drawable-xhdpi/btn_search_dialog_voice_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_search_dialog_voice_selected.9.png b/core/res/res/drawable-xhdpi/btn_search_dialog_voice_selected.9.png
index 2e2f587..e24b69c 100644
--- a/core/res/res/drawable-xhdpi/btn_search_dialog_voice_selected.9.png
+++ b/core/res/res/drawable-xhdpi/btn_search_dialog_voice_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_square_overlay_disabled.png b/core/res/res/drawable-xhdpi/btn_square_overlay_disabled.png
index 3cad470..a04d656 100644
--- a/core/res/res/drawable-xhdpi/btn_square_overlay_disabled.png
+++ b/core/res/res/drawable-xhdpi/btn_square_overlay_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_square_overlay_disabled_focused.png b/core/res/res/drawable-xhdpi/btn_square_overlay_disabled_focused.png
index fff0d50..3d6af36 100644
--- a/core/res/res/drawable-xhdpi/btn_square_overlay_disabled_focused.png
+++ b/core/res/res/drawable-xhdpi/btn_square_overlay_disabled_focused.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_square_overlay_normal.png b/core/res/res/drawable-xhdpi/btn_square_overlay_normal.png
index d2bd151..a7ddfae 100644
--- a/core/res/res/drawable-xhdpi/btn_square_overlay_normal.png
+++ b/core/res/res/drawable-xhdpi/btn_square_overlay_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_square_overlay_pressed.png b/core/res/res/drawable-xhdpi/btn_square_overlay_pressed.png
index b1bf326..f3862ff 100644
--- a/core/res/res/drawable-xhdpi/btn_square_overlay_pressed.png
+++ b/core/res/res/drawable-xhdpi/btn_square_overlay_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_square_overlay_selected.png b/core/res/res/drawable-xhdpi/btn_square_overlay_selected.png
index c48a996..f8cf026 100644
--- a/core/res/res/drawable-xhdpi/btn_square_overlay_selected.png
+++ b/core/res/res/drawable-xhdpi/btn_square_overlay_selected.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_star_big_off.png b/core/res/res/drawable-xhdpi/btn_star_big_off.png
index 4b2abf1..bcb14cd 100644
--- a/core/res/res/drawable-xhdpi/btn_star_big_off.png
+++ b/core/res/res/drawable-xhdpi/btn_star_big_off.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_star_big_off_disable.png b/core/res/res/drawable-xhdpi/btn_star_big_off_disable.png
index c2f8598..d9d4565 100644
--- a/core/res/res/drawable-xhdpi/btn_star_big_off_disable.png
+++ b/core/res/res/drawable-xhdpi/btn_star_big_off_disable.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_star_big_off_disable_focused.png b/core/res/res/drawable-xhdpi/btn_star_big_off_disable_focused.png
index 1d1a1de..ae24abd 100644
--- a/core/res/res/drawable-xhdpi/btn_star_big_off_disable_focused.png
+++ b/core/res/res/drawable-xhdpi/btn_star_big_off_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_star_big_off_pressed.png b/core/res/res/drawable-xhdpi/btn_star_big_off_pressed.png
index c6bb731..6501f6b 100644
--- a/core/res/res/drawable-xhdpi/btn_star_big_off_pressed.png
+++ b/core/res/res/drawable-xhdpi/btn_star_big_off_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_star_big_off_selected.png b/core/res/res/drawable-xhdpi/btn_star_big_off_selected.png
index c25f82e..0cdd125 100644
--- a/core/res/res/drawable-xhdpi/btn_star_big_off_selected.png
+++ b/core/res/res/drawable-xhdpi/btn_star_big_off_selected.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_star_big_on.png b/core/res/res/drawable-xhdpi/btn_star_big_on.png
index 93606c5..d7cbd3d 100644
--- a/core/res/res/drawable-xhdpi/btn_star_big_on.png
+++ b/core/res/res/drawable-xhdpi/btn_star_big_on.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_star_big_on_disable.png b/core/res/res/drawable-xhdpi/btn_star_big_on_disable.png
index c78e42c..4a3786d 100644
--- a/core/res/res/drawable-xhdpi/btn_star_big_on_disable.png
+++ b/core/res/res/drawable-xhdpi/btn_star_big_on_disable.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_star_big_on_disable_focused.png b/core/res/res/drawable-xhdpi/btn_star_big_on_disable_focused.png
index 6b2a537..e0a86a6 100644
--- a/core/res/res/drawable-xhdpi/btn_star_big_on_disable_focused.png
+++ b/core/res/res/drawable-xhdpi/btn_star_big_on_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_star_big_on_pressed.png b/core/res/res/drawable-xhdpi/btn_star_big_on_pressed.png
index a25d0de..7055f8b 100644
--- a/core/res/res/drawable-xhdpi/btn_star_big_on_pressed.png
+++ b/core/res/res/drawable-xhdpi/btn_star_big_on_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_star_big_on_selected.png b/core/res/res/drawable-xhdpi/btn_star_big_on_selected.png
index 4d84628..a82cf9b 100644
--- a/core/res/res/drawable-xhdpi/btn_star_big_on_selected.png
+++ b/core/res/res/drawable-xhdpi/btn_star_big_on_selected.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_star_label_background.9.png b/core/res/res/drawable-xhdpi/btn_star_label_background.9.png
index a8b0568..223ede2 100644
--- a/core/res/res/drawable-xhdpi/btn_star_label_background.9.png
+++ b/core/res/res/drawable-xhdpi/btn_star_label_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_star_mtrl_alpha.png b/core/res/res/drawable-xhdpi/btn_star_mtrl_alpha.png
index a85bc06..5616727 100644
--- a/core/res/res/drawable-xhdpi/btn_star_mtrl_alpha.png
+++ b/core/res/res/drawable-xhdpi/btn_star_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_star_off_disabled_focused_holo_dark.png b/core/res/res/drawable-xhdpi/btn_star_off_disabled_focused_holo_dark.png
index 13a190d..aa26670 100644
--- a/core/res/res/drawable-xhdpi/btn_star_off_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_star_off_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_star_off_disabled_focused_holo_light.png b/core/res/res/drawable-xhdpi/btn_star_off_disabled_focused_holo_light.png
index e9953d9..a3a3135e 100644
--- a/core/res/res/drawable-xhdpi/btn_star_off_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_star_off_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_star_off_disabled_holo_dark.png b/core/res/res/drawable-xhdpi/btn_star_off_disabled_holo_dark.png
index 0f05262..cdfa690 100644
--- a/core/res/res/drawable-xhdpi/btn_star_off_disabled_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_star_off_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_star_off_disabled_holo_light.png b/core/res/res/drawable-xhdpi/btn_star_off_disabled_holo_light.png
index 90243a0..6c1493c 100644
--- a/core/res/res/drawable-xhdpi/btn_star_off_disabled_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_star_off_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_star_off_focused_holo_dark.png b/core/res/res/drawable-xhdpi/btn_star_off_focused_holo_dark.png
index ce667b6..71244a4 100644
--- a/core/res/res/drawable-xhdpi/btn_star_off_focused_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_star_off_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_star_off_focused_holo_light.png b/core/res/res/drawable-xhdpi/btn_star_off_focused_holo_light.png
index fe9cdee..63372bc 100644
--- a/core/res/res/drawable-xhdpi/btn_star_off_focused_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_star_off_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_star_off_normal_holo_dark.png b/core/res/res/drawable-xhdpi/btn_star_off_normal_holo_dark.png
index 392c1be..cd26d95 100644
--- a/core/res/res/drawable-xhdpi/btn_star_off_normal_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_star_off_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_star_off_normal_holo_light.png b/core/res/res/drawable-xhdpi/btn_star_off_normal_holo_light.png
index 28869df0..37ce6ac 100644
--- a/core/res/res/drawable-xhdpi/btn_star_off_normal_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_star_off_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_star_off_pressed_holo_dark.png b/core/res/res/drawable-xhdpi/btn_star_off_pressed_holo_dark.png
index 07c20fd..429c3d9 100644
--- a/core/res/res/drawable-xhdpi/btn_star_off_pressed_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_star_off_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_star_off_pressed_holo_light.png b/core/res/res/drawable-xhdpi/btn_star_off_pressed_holo_light.png
index aabcec2..2e717dd 100644
--- a/core/res/res/drawable-xhdpi/btn_star_off_pressed_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_star_off_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_star_on_disabled_focused_holo_dark.png b/core/res/res/drawable-xhdpi/btn_star_on_disabled_focused_holo_dark.png
index 5ffb71b..f6a35c4 100644
--- a/core/res/res/drawable-xhdpi/btn_star_on_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_star_on_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_star_on_disabled_focused_holo_light.png b/core/res/res/drawable-xhdpi/btn_star_on_disabled_focused_holo_light.png
index 22d0cfb..de010cd 100644
--- a/core/res/res/drawable-xhdpi/btn_star_on_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_star_on_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_star_on_disabled_holo_dark.png b/core/res/res/drawable-xhdpi/btn_star_on_disabled_holo_dark.png
index fdee7fa..fde168b 100644
--- a/core/res/res/drawable-xhdpi/btn_star_on_disabled_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_star_on_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_star_on_disabled_holo_light.png b/core/res/res/drawable-xhdpi/btn_star_on_disabled_holo_light.png
index 7b6534b..32185ef 100644
--- a/core/res/res/drawable-xhdpi/btn_star_on_disabled_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_star_on_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_star_on_focused_holo_dark.png b/core/res/res/drawable-xhdpi/btn_star_on_focused_holo_dark.png
index b4e438a..7dba7f4 100644
--- a/core/res/res/drawable-xhdpi/btn_star_on_focused_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_star_on_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_star_on_focused_holo_light.png b/core/res/res/drawable-xhdpi/btn_star_on_focused_holo_light.png
index 8d19fc9..2c28b94 100644
--- a/core/res/res/drawable-xhdpi/btn_star_on_focused_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_star_on_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_star_on_normal_holo_dark.png b/core/res/res/drawable-xhdpi/btn_star_on_normal_holo_dark.png
index 046df69..39376ce 100644
--- a/core/res/res/drawable-xhdpi/btn_star_on_normal_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_star_on_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_star_on_normal_holo_light.png b/core/res/res/drawable-xhdpi/btn_star_on_normal_holo_light.png
index f17d60b..ab3108f 100644
--- a/core/res/res/drawable-xhdpi/btn_star_on_normal_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_star_on_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_star_on_pressed_holo_dark.png b/core/res/res/drawable-xhdpi/btn_star_on_pressed_holo_dark.png
index 474a25a..39d170f 100644
--- a/core/res/res/drawable-xhdpi/btn_star_on_pressed_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_star_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_star_on_pressed_holo_light.png b/core/res/res/drawable-xhdpi/btn_star_on_pressed_holo_light.png
index f66c059..2f36ba8 100644
--- a/core/res/res/drawable-xhdpi/btn_star_on_pressed_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_star_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00001.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00001.9.png
index df73ef7..b025931 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00001.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00002.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00002.9.png
index baf52ed..ae5d207 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00002.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00003.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00003.9.png
index c8f3b1c..942420eb 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00003.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00004.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00004.9.png
index fe715cf..04b7232 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00004.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00005.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00005.9.png
index 8e66e11..f35158f 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00005.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00006.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00006.9.png
index 537496e..5a20d90 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00006.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00007.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00007.9.png
index 2722a98..458aa51 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00007.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00008.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00008.9.png
index 81fad09..1d7db1b 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00008.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00009.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00009.9.png
index cda20c8..0d07fb7 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00009.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00010.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00010.9.png
index a61ad4b..08c6516 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00010.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00011.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00011.9.png
index d6e8e4c..bbbc14d 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00011.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00012.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00012.9.png
index 785168e..617aa6c 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00012.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00001.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00001.9.png
index 8a648b8..2b1845c 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00001.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00002.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00002.9.png
index 03063d4..6d1b188 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00002.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00003.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00003.9.png
index 6159dec..764b35b 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00003.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00004.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00004.9.png
index 6f1c96c..f543106 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00004.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00005.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00005.9.png
index 2eaff46..cf266f3 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00005.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00006.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00006.9.png
index c4d9db8..50d5b17 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00006.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00007.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00007.9.png
index f276f16..458aa51 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00007.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00008.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00008.9.png
index cf9133e..2574d32 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00008.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00009.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00009.9.png
index 8f1a6a8..fdb9991 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00009.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00010.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00010.9.png
index 5080c46..a7251ec 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00010.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00011.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00011.9.png
index 5e39408..2ba6f5d 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00011.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00012.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00012.9.png
index 435ce21..4d4dc5a 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00012.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_off.9.png b/core/res/res/drawable-xhdpi/btn_toggle_off.9.png
index 1406188..49d6fed 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_off.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_off.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_focused_holo_dark.9.png
index 1e45530..e1e30f9 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_focused_holo_light.9.png
index 1e45530..e1e30f9 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_holo_dark.9.png
index 2c63c5d..dc56ae3 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_holo_light.9.png
index 2c63c5d..dc56ae3 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_off_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_off_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_toggle_off_focused_holo_dark.9.png
index dd5e26e..d20e4a6 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_off_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_off_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_off_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_toggle_off_focused_holo_light.9.png
index dd5e26e..d20e4a6 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_off_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_off_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_off_normal_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_toggle_off_normal_holo_dark.9.png
index aa9b3c5..defd083 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_off_normal_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_off_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_off_normal_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_toggle_off_normal_holo_light.9.png
index 367c25a..afc4f12 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_off_normal_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_off_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_off_pressed_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_toggle_off_pressed_holo_dark.9.png
index ce3d0d9..d124787 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_off_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_off_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_off_pressed_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_toggle_off_pressed_holo_light.9.png
index 9d07941..094c640 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_off_pressed_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_off_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_on.9.png b/core/res/res/drawable-xhdpi/btn_toggle_on.9.png
index 90f1e7b..252e129 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_on.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_on.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_focused_holo_dark.9.png
index df28ad0..e38853e 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_focused_holo_light.9.png
index df28ad0..e38853e 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_holo_dark.9.png
index 3a27831..d8bdec8 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_holo_light.9.png
index 3a27831..d8bdec8 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_on_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_on_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_toggle_on_focused_holo_dark.9.png
index d68bdf4..7db5299 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_on_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_on_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_on_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_toggle_on_focused_holo_light.9.png
index d68bdf4..7db5299 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_on_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_on_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_on_normal_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_toggle_on_normal_holo_dark.9.png
index da03ec9..5b2cb88 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_on_normal_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_on_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_on_normal_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_toggle_on_normal_holo_light.9.png
index 482b249..6b59455 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_on_normal_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_on_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_on_pressed_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_toggle_on_pressed_holo_dark.9.png
index ab794db..dfb0830 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_on_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_on_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_on_pressed_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_toggle_on_pressed_holo_light.9.png
index 2ea1047..5b15aa8 100644
--- a/core/res/res/drawable-xhdpi/btn_toggle_on_pressed_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_toggle_on_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_zoom_down_disabled.9.png b/core/res/res/drawable-xhdpi/btn_zoom_down_disabled.9.png
index 7e4297b..a7c6f87 100644
--- a/core/res/res/drawable-xhdpi/btn_zoom_down_disabled.9.png
+++ b/core/res/res/drawable-xhdpi/btn_zoom_down_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_zoom_down_disabled_focused.9.png b/core/res/res/drawable-xhdpi/btn_zoom_down_disabled_focused.9.png
index f23f23c..96fe2e9 100644
--- a/core/res/res/drawable-xhdpi/btn_zoom_down_disabled_focused.9.png
+++ b/core/res/res/drawable-xhdpi/btn_zoom_down_disabled_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_zoom_down_normal.9.png b/core/res/res/drawable-xhdpi/btn_zoom_down_normal.9.png
index 59ae103..165a127 100644
--- a/core/res/res/drawable-xhdpi/btn_zoom_down_normal.9.png
+++ b/core/res/res/drawable-xhdpi/btn_zoom_down_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_zoom_down_pressed.9.png b/core/res/res/drawable-xhdpi/btn_zoom_down_pressed.9.png
index 23c19c1..cd8f7fd 100644
--- a/core/res/res/drawable-xhdpi/btn_zoom_down_pressed.9.png
+++ b/core/res/res/drawable-xhdpi/btn_zoom_down_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_zoom_down_selected.9.png b/core/res/res/drawable-xhdpi/btn_zoom_down_selected.9.png
index 9066821..181f8d2 100644
--- a/core/res/res/drawable-xhdpi/btn_zoom_down_selected.9.png
+++ b/core/res/res/drawable-xhdpi/btn_zoom_down_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_zoom_page_normal.png b/core/res/res/drawable-xhdpi/btn_zoom_page_normal.png
index 9ae3f50..a58ae12 100644
--- a/core/res/res/drawable-xhdpi/btn_zoom_page_normal.png
+++ b/core/res/res/drawable-xhdpi/btn_zoom_page_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_zoom_page_press.png b/core/res/res/drawable-xhdpi/btn_zoom_page_press.png
index 3549bdf..a7e427b 100644
--- a/core/res/res/drawable-xhdpi/btn_zoom_page_press.png
+++ b/core/res/res/drawable-xhdpi/btn_zoom_page_press.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_zoom_up_disabled.9.png b/core/res/res/drawable-xhdpi/btn_zoom_up_disabled.9.png
index 6bc9e2e..72e8523 100644
--- a/core/res/res/drawable-xhdpi/btn_zoom_up_disabled.9.png
+++ b/core/res/res/drawable-xhdpi/btn_zoom_up_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_zoom_up_disabled_focused.9.png b/core/res/res/drawable-xhdpi/btn_zoom_up_disabled_focused.9.png
index 8dc0568..2bd7d58 100644
--- a/core/res/res/drawable-xhdpi/btn_zoom_up_disabled_focused.9.png
+++ b/core/res/res/drawable-xhdpi/btn_zoom_up_disabled_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_zoom_up_normal.9.png b/core/res/res/drawable-xhdpi/btn_zoom_up_normal.9.png
index 7776d28..6d59784 100644
--- a/core/res/res/drawable-xhdpi/btn_zoom_up_normal.9.png
+++ b/core/res/res/drawable-xhdpi/btn_zoom_up_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_zoom_up_pressed.9.png b/core/res/res/drawable-xhdpi/btn_zoom_up_pressed.9.png
index 2a5b1f4..d104f77 100644
--- a/core/res/res/drawable-xhdpi/btn_zoom_up_pressed.9.png
+++ b/core/res/res/drawable-xhdpi/btn_zoom_up_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_zoom_up_selected.9.png b/core/res/res/drawable-xhdpi/btn_zoom_up_selected.9.png
index f88c377..96cdbd39 100644
--- a/core/res/res/drawable-xhdpi/btn_zoom_up_selected.9.png
+++ b/core/res/res/drawable-xhdpi/btn_zoom_up_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/button_onoff_indicator_off.png b/core/res/res/drawable-xhdpi/button_onoff_indicator_off.png
index f70fd68..241cf49 100644
--- a/core/res/res/drawable-xhdpi/button_onoff_indicator_off.png
+++ b/core/res/res/drawable-xhdpi/button_onoff_indicator_off.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/button_onoff_indicator_on.png b/core/res/res/drawable-xhdpi/button_onoff_indicator_on.png
index 9163be4..d0f5767 100644
--- a/core/res/res/drawable-xhdpi/button_onoff_indicator_on.png
+++ b/core/res/res/drawable-xhdpi/button_onoff_indicator_on.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/cab_background_bottom_holo_dark.9.png b/core/res/res/drawable-xhdpi/cab_background_bottom_holo_dark.9.png
index 0bd0980..d17b95d 100644
--- a/core/res/res/drawable-xhdpi/cab_background_bottom_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/cab_background_bottom_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/cab_background_bottom_holo_light.9.png b/core/res/res/drawable-xhdpi/cab_background_bottom_holo_light.9.png
index 43ed26d..4c2c347 100644
--- a/core/res/res/drawable-xhdpi/cab_background_bottom_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/cab_background_bottom_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/cab_background_bottom_mtrl_alpha.9.png b/core/res/res/drawable-xhdpi/cab_background_bottom_mtrl_alpha.9.png
index 9a4abd0..4923fd9 100644
--- a/core/res/res/drawable-xhdpi/cab_background_bottom_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xhdpi/cab_background_bottom_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/cab_background_top_holo_dark.9.png b/core/res/res/drawable-xhdpi/cab_background_top_holo_dark.9.png
index 7b6d48b..a07d526 100644
--- a/core/res/res/drawable-xhdpi/cab_background_top_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/cab_background_top_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/cab_background_top_holo_light.9.png b/core/res/res/drawable-xhdpi/cab_background_top_holo_light.9.png
index bafe878..cf04650 100644
--- a/core/res/res/drawable-xhdpi/cab_background_top_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/cab_background_top_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/cab_background_top_mtrl_alpha.9.png b/core/res/res/drawable-xhdpi/cab_background_top_mtrl_alpha.9.png
index ed8d3411..f5636be 100644
--- a/core/res/res/drawable-xhdpi/cab_background_top_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xhdpi/cab_background_top_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/call_contact.png b/core/res/res/drawable-xhdpi/call_contact.png
index 343e2db..b19dea8 100644
--- a/core/res/res/drawable-xhdpi/call_contact.png
+++ b/core/res/res/drawable-xhdpi/call_contact.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/checkbox_off_background.png b/core/res/res/drawable-xhdpi/checkbox_off_background.png
index ade4c0a..553227c 100644
--- a/core/res/res/drawable-xhdpi/checkbox_off_background.png
+++ b/core/res/res/drawable-xhdpi/checkbox_off_background.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/checkbox_on_background.png b/core/res/res/drawable-xhdpi/checkbox_on_background.png
index 5f6803a..709cf8f 100644
--- a/core/res/res/drawable-xhdpi/checkbox_on_background.png
+++ b/core/res/res/drawable-xhdpi/checkbox_on_background.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/cling_arrow_up.png b/core/res/res/drawable-xhdpi/cling_arrow_up.png
index 2803155..f3219e3 100644
--- a/core/res/res/drawable-xhdpi/cling_arrow_up.png
+++ b/core/res/res/drawable-xhdpi/cling_arrow_up.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/cling_bg.9.png b/core/res/res/drawable-xhdpi/cling_bg.9.png
index 1cb4681..9fc6b9c 100644
--- a/core/res/res/drawable-xhdpi/cling_bg.9.png
+++ b/core/res/res/drawable-xhdpi/cling_bg.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/cling_button_normal.9.png b/core/res/res/drawable-xhdpi/cling_button_normal.9.png
index 4192563..092d015 100644
--- a/core/res/res/drawable-xhdpi/cling_button_normal.9.png
+++ b/core/res/res/drawable-xhdpi/cling_button_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/cling_button_pressed.9.png b/core/res/res/drawable-xhdpi/cling_button_pressed.9.png
index d3ce469..fd517fc 100644
--- a/core/res/res/drawable-xhdpi/cling_button_pressed.9.png
+++ b/core/res/res/drawable-xhdpi/cling_button_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/code_lock_bottom.9.png b/core/res/res/drawable-xhdpi/code_lock_bottom.9.png
index 1dbab24..b7a04c7 100644
--- a/core/res/res/drawable-xhdpi/code_lock_bottom.9.png
+++ b/core/res/res/drawable-xhdpi/code_lock_bottom.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/code_lock_left.9.png b/core/res/res/drawable-xhdpi/code_lock_left.9.png
index ae65521..96494b6 100644
--- a/core/res/res/drawable-xhdpi/code_lock_left.9.png
+++ b/core/res/res/drawable-xhdpi/code_lock_left.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/code_lock_top.9.png b/core/res/res/drawable-xhdpi/code_lock_top.9.png
index 31517e4..c04548f 100644
--- a/core/res/res/drawable-xhdpi/code_lock_top.9.png
+++ b/core/res/res/drawable-xhdpi/code_lock_top.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/combobox_disabled.png b/core/res/res/drawable-xhdpi/combobox_disabled.png
index e8ca0b0..94253b3 100644
--- a/core/res/res/drawable-xhdpi/combobox_disabled.png
+++ b/core/res/res/drawable-xhdpi/combobox_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/combobox_nohighlight.png b/core/res/res/drawable-xhdpi/combobox_nohighlight.png
index d75bb06..972be7b 100644
--- a/core/res/res/drawable-xhdpi/combobox_nohighlight.png
+++ b/core/res/res/drawable-xhdpi/combobox_nohighlight.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/compass_arrow.png b/core/res/res/drawable-xhdpi/compass_arrow.png
index 1d0f360..9d4bc78 100644
--- a/core/res/res/drawable-xhdpi/compass_arrow.png
+++ b/core/res/res/drawable-xhdpi/compass_arrow.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/compass_base.png b/core/res/res/drawable-xhdpi/compass_base.png
index a66eb4a..a47d448 100644
--- a/core/res/res/drawable-xhdpi/compass_base.png
+++ b/core/res/res/drawable-xhdpi/compass_base.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/contact_header_bg.9.png b/core/res/res/drawable-xhdpi/contact_header_bg.9.png
index bde1d56..d5a3430 100644
--- a/core/res/res/drawable-xhdpi/contact_header_bg.9.png
+++ b/core/res/res/drawable-xhdpi/contact_header_bg.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/create_contact.png b/core/res/res/drawable-xhdpi/create_contact.png
index c6d5622..648c22b 100644
--- a/core/res/res/drawable-xhdpi/create_contact.png
+++ b/core/res/res/drawable-xhdpi/create_contact.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dark_header.9.png b/core/res/res/drawable-xhdpi/dark_header.9.png
index 5a0adc8..72eb7e4 100644
--- a/core/res/res/drawable-xhdpi/dark_header.9.png
+++ b/core/res/res/drawable-xhdpi/dark_header.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/day_picker_week_view_dayline_holo.9.png b/core/res/res/drawable-xhdpi/day_picker_week_view_dayline_holo.9.png
index 701a1b2..ac7c65a 100644
--- a/core/res/res/drawable-xhdpi/day_picker_week_view_dayline_holo.9.png
+++ b/core/res/res/drawable-xhdpi/day_picker_week_view_dayline_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_bottom_holo_dark.9.png b/core/res/res/drawable-xhdpi/dialog_bottom_holo_dark.9.png
index 3c26c6b..9649eaf 100644
--- a/core/res/res/drawable-xhdpi/dialog_bottom_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_bottom_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_bottom_holo_light.9.png b/core/res/res/drawable-xhdpi/dialog_bottom_holo_light.9.png
index f7423f3..dd8e145 100644
--- a/core/res/res/drawable-xhdpi/dialog_bottom_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_bottom_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_divider_horizontal_holo_dark.9.png b/core/res/res/drawable-xhdpi/dialog_divider_horizontal_holo_dark.9.png
index e966846..488c8c9 100644
--- a/core/res/res/drawable-xhdpi/dialog_divider_horizontal_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_divider_horizontal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_divider_horizontal_holo_light.9.png b/core/res/res/drawable-xhdpi/dialog_divider_horizontal_holo_light.9.png
index 093802b..f27ca00 100644
--- a/core/res/res/drawable-xhdpi/dialog_divider_horizontal_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_divider_horizontal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_divider_horizontal_light.9.png b/core/res/res/drawable-xhdpi/dialog_divider_horizontal_light.9.png
index 02aa017..d808a80 100644
--- a/core/res/res/drawable-xhdpi/dialog_divider_horizontal_light.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_divider_horizontal_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_full_holo_dark.9.png b/core/res/res/drawable-xhdpi/dialog_full_holo_dark.9.png
index 75d36be..3beaaf8 100644
--- a/core/res/res/drawable-xhdpi/dialog_full_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_full_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_full_holo_light.9.png b/core/res/res/drawable-xhdpi/dialog_full_holo_light.9.png
index d9bd337..c3bdc3f 100644
--- a/core/res/res/drawable-xhdpi/dialog_full_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_full_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_ic_close_focused_holo_dark.png b/core/res/res/drawable-xhdpi/dialog_ic_close_focused_holo_dark.png
index aa473ab..9c084d3 100644
--- a/core/res/res/drawable-xhdpi/dialog_ic_close_focused_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/dialog_ic_close_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_ic_close_focused_holo_light.png b/core/res/res/drawable-xhdpi/dialog_ic_close_focused_holo_light.png
index ab21bbe..7d6b6ed 100644
--- a/core/res/res/drawable-xhdpi/dialog_ic_close_focused_holo_light.png
+++ b/core/res/res/drawable-xhdpi/dialog_ic_close_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_ic_close_normal_holo_dark.png b/core/res/res/drawable-xhdpi/dialog_ic_close_normal_holo_dark.png
index 338e1b7..e91da07 100644
--- a/core/res/res/drawable-xhdpi/dialog_ic_close_normal_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/dialog_ic_close_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_ic_close_normal_holo_light.png b/core/res/res/drawable-xhdpi/dialog_ic_close_normal_holo_light.png
index e11f2e3..a22a151 100644
--- a/core/res/res/drawable-xhdpi/dialog_ic_close_normal_holo_light.png
+++ b/core/res/res/drawable-xhdpi/dialog_ic_close_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_ic_close_pressed_holo_dark.png b/core/res/res/drawable-xhdpi/dialog_ic_close_pressed_holo_dark.png
index 0401bcd..7aaf7d4 100644
--- a/core/res/res/drawable-xhdpi/dialog_ic_close_pressed_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/dialog_ic_close_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_ic_close_pressed_holo_light.png b/core/res/res/drawable-xhdpi/dialog_ic_close_pressed_holo_light.png
index 7040392..64596e3 100644
--- a/core/res/res/drawable-xhdpi/dialog_ic_close_pressed_holo_light.png
+++ b/core/res/res/drawable-xhdpi/dialog_ic_close_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_middle_holo_dark.9.png b/core/res/res/drawable-xhdpi/dialog_middle_holo_dark.9.png
index e9467b4..9451180 100644
--- a/core/res/res/drawable-xhdpi/dialog_middle_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_middle_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_middle_holo_light.9.png b/core/res/res/drawable-xhdpi/dialog_middle_holo_light.9.png
index ce3a880..35a59bb 100644
--- a/core/res/res/drawable-xhdpi/dialog_middle_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_middle_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_top_holo_dark.9.png b/core/res/res/drawable-xhdpi/dialog_top_holo_dark.9.png
index fa95667..d99dba4 100644
--- a/core/res/res/drawable-xhdpi/dialog_top_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_top_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_top_holo_light.9.png b/core/res/res/drawable-xhdpi/dialog_top_holo_light.9.png
index 555fb81..4f68936 100644
--- a/core/res/res/drawable-xhdpi/dialog_top_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_top_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/divider_horizontal_bright.9.png b/core/res/res/drawable-xhdpi/divider_horizontal_bright.9.png
index 41b776b..f355428 100644
--- a/core/res/res/drawable-xhdpi/divider_horizontal_bright.9.png
+++ b/core/res/res/drawable-xhdpi/divider_horizontal_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/divider_horizontal_bright_opaque.9.png b/core/res/res/drawable-xhdpi/divider_horizontal_bright_opaque.9.png
index eb75a22..72909ae 100644
--- a/core/res/res/drawable-xhdpi/divider_horizontal_bright_opaque.9.png
+++ b/core/res/res/drawable-xhdpi/divider_horizontal_bright_opaque.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/divider_horizontal_dark.9.png b/core/res/res/drawable-xhdpi/divider_horizontal_dark.9.png
index 55a5e53..87769d6 100644
--- a/core/res/res/drawable-xhdpi/divider_horizontal_dark.9.png
+++ b/core/res/res/drawable-xhdpi/divider_horizontal_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/divider_horizontal_dark_opaque.9.png b/core/res/res/drawable-xhdpi/divider_horizontal_dark_opaque.9.png
index 60e2cb2..12ff35d 100644
--- a/core/res/res/drawable-xhdpi/divider_horizontal_dark_opaque.9.png
+++ b/core/res/res/drawable-xhdpi/divider_horizontal_dark_opaque.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/divider_horizontal_dim_dark.9.png b/core/res/res/drawable-xhdpi/divider_horizontal_dim_dark.9.png
index cf34613..91c18c1 100644
--- a/core/res/res/drawable-xhdpi/divider_horizontal_dim_dark.9.png
+++ b/core/res/res/drawable-xhdpi/divider_horizontal_dim_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/divider_horizontal_holo_dark.9.png b/core/res/res/drawable-xhdpi/divider_horizontal_holo_dark.9.png
index 48a88b8..dc18d9e 100644
--- a/core/res/res/drawable-xhdpi/divider_horizontal_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/divider_horizontal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/divider_horizontal_holo_light.9.png b/core/res/res/drawable-xhdpi/divider_horizontal_holo_light.9.png
index 712aef2..877a429 100644
--- a/core/res/res/drawable-xhdpi/divider_horizontal_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/divider_horizontal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/divider_horizontal_textfield.9.png b/core/res/res/drawable-xhdpi/divider_horizontal_textfield.9.png
index c9fa0fd..1fed888 100644
--- a/core/res/res/drawable-xhdpi/divider_horizontal_textfield.9.png
+++ b/core/res/res/drawable-xhdpi/divider_horizontal_textfield.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/divider_vertical_bright.9.png b/core/res/res/drawable-xhdpi/divider_vertical_bright.9.png
index 41b776b..f355428 100644
--- a/core/res/res/drawable-xhdpi/divider_vertical_bright.9.png
+++ b/core/res/res/drawable-xhdpi/divider_vertical_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/divider_vertical_bright_opaque.9.png b/core/res/res/drawable-xhdpi/divider_vertical_bright_opaque.9.png
index eb75a22..08bc1fc 100644
--- a/core/res/res/drawable-xhdpi/divider_vertical_bright_opaque.9.png
+++ b/core/res/res/drawable-xhdpi/divider_vertical_bright_opaque.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/divider_vertical_dark.9.png b/core/res/res/drawable-xhdpi/divider_vertical_dark.9.png
index 55a5e53..87769d6 100644
--- a/core/res/res/drawable-xhdpi/divider_vertical_dark.9.png
+++ b/core/res/res/drawable-xhdpi/divider_vertical_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/divider_vertical_dark_opaque.9.png b/core/res/res/drawable-xhdpi/divider_vertical_dark_opaque.9.png
index 60e2cb2..7e34600 100644
--- a/core/res/res/drawable-xhdpi/divider_vertical_dark_opaque.9.png
+++ b/core/res/res/drawable-xhdpi/divider_vertical_dark_opaque.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/divider_vertical_holo_dark.9.png b/core/res/res/drawable-xhdpi/divider_vertical_holo_dark.9.png
index 9666f73..18e424d 100644
--- a/core/res/res/drawable-xhdpi/divider_vertical_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/divider_vertical_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/divider_vertical_holo_light.9.png b/core/res/res/drawable-xhdpi/divider_vertical_holo_light.9.png
index 026017b..e732a3b 100644
--- a/core/res/res/drawable-xhdpi/divider_vertical_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/divider_vertical_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dropdown_disabled_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/dropdown_disabled_focused_holo_dark.9.png
index b5d226a..912e250 100644
--- a/core/res/res/drawable-xhdpi/dropdown_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/dropdown_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dropdown_disabled_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/dropdown_disabled_focused_holo_light.9.png
index af85561..2de812f 100644
--- a/core/res/res/drawable-xhdpi/dropdown_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/dropdown_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dropdown_disabled_holo_dark.9.png b/core/res/res/drawable-xhdpi/dropdown_disabled_holo_dark.9.png
index bf01b0a..951bda5 100644
--- a/core/res/res/drawable-xhdpi/dropdown_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/dropdown_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dropdown_disabled_holo_light.9.png b/core/res/res/drawable-xhdpi/dropdown_disabled_holo_light.9.png
index f4effa1..ec5a90e 100644
--- a/core/res/res/drawable-xhdpi/dropdown_disabled_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/dropdown_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dropdown_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/dropdown_focused_holo_dark.9.png
index ce31d0f..b990b4f 100644
--- a/core/res/res/drawable-xhdpi/dropdown_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/dropdown_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dropdown_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/dropdown_focused_holo_light.9.png
index 4596171..b346c12 100644
--- a/core/res/res/drawable-xhdpi/dropdown_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/dropdown_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dropdown_ic_arrow_disabled_focused_holo_dark.png b/core/res/res/drawable-xhdpi/dropdown_ic_arrow_disabled_focused_holo_dark.png
index adb6c36..31cf8d1 100644
--- a/core/res/res/drawable-xhdpi/dropdown_ic_arrow_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/dropdown_ic_arrow_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dropdown_ic_arrow_disabled_focused_holo_light.png b/core/res/res/drawable-xhdpi/dropdown_ic_arrow_disabled_focused_holo_light.png
index a1075d5..049f139 100644
--- a/core/res/res/drawable-xhdpi/dropdown_ic_arrow_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-xhdpi/dropdown_ic_arrow_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dropdown_ic_arrow_disabled_holo_dark.png b/core/res/res/drawable-xhdpi/dropdown_ic_arrow_disabled_holo_dark.png
index 782325f..3d26bb3 100644
--- a/core/res/res/drawable-xhdpi/dropdown_ic_arrow_disabled_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/dropdown_ic_arrow_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dropdown_ic_arrow_disabled_holo_light.png b/core/res/res/drawable-xhdpi/dropdown_ic_arrow_disabled_holo_light.png
index 195ecbb..2da00fc 100644
--- a/core/res/res/drawable-xhdpi/dropdown_ic_arrow_disabled_holo_light.png
+++ b/core/res/res/drawable-xhdpi/dropdown_ic_arrow_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dropdown_ic_arrow_focused_holo_light.png b/core/res/res/drawable-xhdpi/dropdown_ic_arrow_focused_holo_light.png
index 988e3f4..778f87c 100644
--- a/core/res/res/drawable-xhdpi/dropdown_ic_arrow_focused_holo_light.png
+++ b/core/res/res/drawable-xhdpi/dropdown_ic_arrow_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dropdown_ic_arrow_normal_holo_dark.png b/core/res/res/drawable-xhdpi/dropdown_ic_arrow_normal_holo_dark.png
index 36d8cf4..7d1bddb 100644
--- a/core/res/res/drawable-xhdpi/dropdown_ic_arrow_normal_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/dropdown_ic_arrow_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dropdown_ic_arrow_normal_holo_light.png b/core/res/res/drawable-xhdpi/dropdown_ic_arrow_normal_holo_light.png
index a931132..a0ae183 100644
--- a/core/res/res/drawable-xhdpi/dropdown_ic_arrow_normal_holo_light.png
+++ b/core/res/res/drawable-xhdpi/dropdown_ic_arrow_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dropdown_ic_arrow_pressed_holo_light.png b/core/res/res/drawable-xhdpi/dropdown_ic_arrow_pressed_holo_light.png
index 833bc13..3dbab4d 100644
--- a/core/res/res/drawable-xhdpi/dropdown_ic_arrow_pressed_holo_light.png
+++ b/core/res/res/drawable-xhdpi/dropdown_ic_arrow_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dropdown_normal_holo_dark.9.png b/core/res/res/drawable-xhdpi/dropdown_normal_holo_dark.9.png
index ca18b0d..3e3d1ea 100644
--- a/core/res/res/drawable-xhdpi/dropdown_normal_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/dropdown_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dropdown_normal_holo_light.9.png b/core/res/res/drawable-xhdpi/dropdown_normal_holo_light.9.png
index 37ad0e0..2d51d99 100644
--- a/core/res/res/drawable-xhdpi/dropdown_normal_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/dropdown_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dropdown_pressed_holo_dark.9.png b/core/res/res/drawable-xhdpi/dropdown_pressed_holo_dark.9.png
index bdee422..49de215 100644
--- a/core/res/res/drawable-xhdpi/dropdown_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/dropdown_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dropdown_pressed_holo_light.9.png b/core/res/res/drawable-xhdpi/dropdown_pressed_holo_light.9.png
index 12ea0548..8c40cfd 100644
--- a/core/res/res/drawable-xhdpi/dropdown_pressed_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/dropdown_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/edit_query.png b/core/res/res/drawable-xhdpi/edit_query.png
index dea9701..a2d0e70 100644
--- a/core/res/res/drawable-xhdpi/edit_query.png
+++ b/core/res/res/drawable-xhdpi/edit_query.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/edit_query_background_normal.9.png b/core/res/res/drawable-xhdpi/edit_query_background_normal.9.png
index 7787df3..9a08ad5 100644
--- a/core/res/res/drawable-xhdpi/edit_query_background_normal.9.png
+++ b/core/res/res/drawable-xhdpi/edit_query_background_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/edit_query_background_pressed.9.png b/core/res/res/drawable-xhdpi/edit_query_background_pressed.9.png
index af81b2f..dc3fdc0 100644
--- a/core/res/res/drawable-xhdpi/edit_query_background_pressed.9.png
+++ b/core/res/res/drawable-xhdpi/edit_query_background_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/edit_query_background_selected.9.png b/core/res/res/drawable-xhdpi/edit_query_background_selected.9.png
index b4f0f59..8754f09 100644
--- a/core/res/res/drawable-xhdpi/edit_query_background_selected.9.png
+++ b/core/res/res/drawable-xhdpi/edit_query_background_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/editbox_background_focus_yellow.9.png b/core/res/res/drawable-xhdpi/editbox_background_focus_yellow.9.png
index c4fdda1..c322df5 100644
--- a/core/res/res/drawable-xhdpi/editbox_background_focus_yellow.9.png
+++ b/core/res/res/drawable-xhdpi/editbox_background_focus_yellow.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/editbox_background_normal.9.png b/core/res/res/drawable-xhdpi/editbox_background_normal.9.png
index e1ee276..b6f6d58 100644
--- a/core/res/res/drawable-xhdpi/editbox_background_normal.9.png
+++ b/core/res/res/drawable-xhdpi/editbox_background_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/editbox_dropdown_background.9.png b/core/res/res/drawable-xhdpi/editbox_dropdown_background.9.png
index ac9de9a..b4384d3 100644
--- a/core/res/res/drawable-xhdpi/editbox_dropdown_background.9.png
+++ b/core/res/res/drawable-xhdpi/editbox_dropdown_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/editbox_dropdown_background_dark.9.png b/core/res/res/drawable-xhdpi/editbox_dropdown_background_dark.9.png
index 439a856..ed5ebbe 100644
--- a/core/res/res/drawable-xhdpi/editbox_dropdown_background_dark.9.png
+++ b/core/res/res/drawable-xhdpi/editbox_dropdown_background_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/emo_im_angel.png b/core/res/res/drawable-xhdpi/emo_im_angel.png
index 8853cbe..c748fc0 100644
--- a/core/res/res/drawable-xhdpi/emo_im_angel.png
+++ b/core/res/res/drawable-xhdpi/emo_im_angel.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/emo_im_cool.png b/core/res/res/drawable-xhdpi/emo_im_cool.png
index 82cbd55d..d8e506f5 100644
--- a/core/res/res/drawable-xhdpi/emo_im_cool.png
+++ b/core/res/res/drawable-xhdpi/emo_im_cool.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/emo_im_crying.png b/core/res/res/drawable-xhdpi/emo_im_crying.png
index 3151125..fe54332 100644
--- a/core/res/res/drawable-xhdpi/emo_im_crying.png
+++ b/core/res/res/drawable-xhdpi/emo_im_crying.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/emo_im_embarrassed.png b/core/res/res/drawable-xhdpi/emo_im_embarrassed.png
index ef2fded..09c2eb2 100644
--- a/core/res/res/drawable-xhdpi/emo_im_embarrassed.png
+++ b/core/res/res/drawable-xhdpi/emo_im_embarrassed.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/emo_im_foot_in_mouth.png b/core/res/res/drawable-xhdpi/emo_im_foot_in_mouth.png
index c41b19d..bec95c8 100644
--- a/core/res/res/drawable-xhdpi/emo_im_foot_in_mouth.png
+++ b/core/res/res/drawable-xhdpi/emo_im_foot_in_mouth.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/emo_im_happy.png b/core/res/res/drawable-xhdpi/emo_im_happy.png
index a2702b2..75761f8 100644
--- a/core/res/res/drawable-xhdpi/emo_im_happy.png
+++ b/core/res/res/drawable-xhdpi/emo_im_happy.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/emo_im_kissing.png b/core/res/res/drawable-xhdpi/emo_im_kissing.png
index 7afd2f6..f63a2ac 100644
--- a/core/res/res/drawable-xhdpi/emo_im_kissing.png
+++ b/core/res/res/drawable-xhdpi/emo_im_kissing.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/emo_im_laughing.png b/core/res/res/drawable-xhdpi/emo_im_laughing.png
index abc3700..a640e4a 100644
--- a/core/res/res/drawable-xhdpi/emo_im_laughing.png
+++ b/core/res/res/drawable-xhdpi/emo_im_laughing.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/emo_im_lips_are_sealed.png b/core/res/res/drawable-xhdpi/emo_im_lips_are_sealed.png
index 60592fb..7822367c 100644
--- a/core/res/res/drawable-xhdpi/emo_im_lips_are_sealed.png
+++ b/core/res/res/drawable-xhdpi/emo_im_lips_are_sealed.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/emo_im_money_mouth.png b/core/res/res/drawable-xhdpi/emo_im_money_mouth.png
index 8efcf0b..ce72dfa 100644
--- a/core/res/res/drawable-xhdpi/emo_im_money_mouth.png
+++ b/core/res/res/drawable-xhdpi/emo_im_money_mouth.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/emo_im_sad.png b/core/res/res/drawable-xhdpi/emo_im_sad.png
index 81e94b1..1d0b34b 100644
--- a/core/res/res/drawable-xhdpi/emo_im_sad.png
+++ b/core/res/res/drawable-xhdpi/emo_im_sad.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/emo_im_surprised.png b/core/res/res/drawable-xhdpi/emo_im_surprised.png
index 7b7aabf..104fb5e 100644
--- a/core/res/res/drawable-xhdpi/emo_im_surprised.png
+++ b/core/res/res/drawable-xhdpi/emo_im_surprised.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/emo_im_tongue_sticking_out.png b/core/res/res/drawable-xhdpi/emo_im_tongue_sticking_out.png
index 1b6a985..a9d104d 100644
--- a/core/res/res/drawable-xhdpi/emo_im_tongue_sticking_out.png
+++ b/core/res/res/drawable-xhdpi/emo_im_tongue_sticking_out.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/emo_im_undecided.png b/core/res/res/drawable-xhdpi/emo_im_undecided.png
index 2c2cfa6..155ee42 100644
--- a/core/res/res/drawable-xhdpi/emo_im_undecided.png
+++ b/core/res/res/drawable-xhdpi/emo_im_undecided.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/emo_im_winking.png b/core/res/res/drawable-xhdpi/emo_im_winking.png
index 6c9cb0e..95ca75b 100644
--- a/core/res/res/drawable-xhdpi/emo_im_winking.png
+++ b/core/res/res/drawable-xhdpi/emo_im_winking.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/emo_im_wtf.png b/core/res/res/drawable-xhdpi/emo_im_wtf.png
index 34861e4..c639d6c 100644
--- a/core/res/res/drawable-xhdpi/emo_im_wtf.png
+++ b/core/res/res/drawable-xhdpi/emo_im_wtf.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/emo_im_yelling.png b/core/res/res/drawable-xhdpi/emo_im_yelling.png
index 0583178..4a33a52 100644
--- a/core/res/res/drawable-xhdpi/emo_im_yelling.png
+++ b/core/res/res/drawable-xhdpi/emo_im_yelling.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/expander_close_holo_dark.9.png b/core/res/res/drawable-xhdpi/expander_close_holo_dark.9.png
index f56ef31..5fc7316 100644
--- a/core/res/res/drawable-xhdpi/expander_close_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/expander_close_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/expander_close_holo_light.9.png b/core/res/res/drawable-xhdpi/expander_close_holo_light.9.png
index e157024..65017a6 100644
--- a/core/res/res/drawable-xhdpi/expander_close_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/expander_close_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/expander_close_mtrl_alpha.9.png b/core/res/res/drawable-xhdpi/expander_close_mtrl_alpha.9.png
index 43dccf3..b3e848d 100644
--- a/core/res/res/drawable-xhdpi/expander_close_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xhdpi/expander_close_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/expander_ic_maximized.9.png b/core/res/res/drawable-xhdpi/expander_ic_maximized.9.png
index 598b75b..6b0bd80 100644
--- a/core/res/res/drawable-xhdpi/expander_ic_maximized.9.png
+++ b/core/res/res/drawable-xhdpi/expander_ic_maximized.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/expander_ic_minimized.9.png b/core/res/res/drawable-xhdpi/expander_ic_minimized.9.png
index 396f4138..9615666 100644
--- a/core/res/res/drawable-xhdpi/expander_ic_minimized.9.png
+++ b/core/res/res/drawable-xhdpi/expander_ic_minimized.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/expander_open_holo_dark.9.png b/core/res/res/drawable-xhdpi/expander_open_holo_dark.9.png
index d2e8ae8..710c7fe 100644
--- a/core/res/res/drawable-xhdpi/expander_open_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/expander_open_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/expander_open_holo_light.9.png b/core/res/res/drawable-xhdpi/expander_open_holo_light.9.png
index 35fb75a..faacaf2 100644
--- a/core/res/res/drawable-xhdpi/expander_open_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/expander_open_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/expander_open_mtrl_alpha.9.png b/core/res/res/drawable-xhdpi/expander_open_mtrl_alpha.9.png
index 181be1a..038b3a6 100644
--- a/core/res/res/drawable-xhdpi/expander_open_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xhdpi/expander_open_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/fastscroll_label_left_holo_dark.9.png b/core/res/res/drawable-xhdpi/fastscroll_label_left_holo_dark.9.png
index 6e0244f..cf3493e 100644
--- a/core/res/res/drawable-xhdpi/fastscroll_label_left_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/fastscroll_label_left_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/fastscroll_label_left_holo_light.9.png b/core/res/res/drawable-xhdpi/fastscroll_label_left_holo_light.9.png
index 6478a11..d1e9ed6 100644
--- a/core/res/res/drawable-xhdpi/fastscroll_label_left_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/fastscroll_label_left_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/fastscroll_label_right_holo_dark.9.png b/core/res/res/drawable-xhdpi/fastscroll_label_right_holo_dark.9.png
index 0330b17..2f46b6a 100644
--- a/core/res/res/drawable-xhdpi/fastscroll_label_right_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/fastscroll_label_right_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/fastscroll_label_right_holo_light.9.png b/core/res/res/drawable-xhdpi/fastscroll_label_right_holo_light.9.png
index 57539e4..90f3738 100644
--- a/core/res/res/drawable-xhdpi/fastscroll_label_right_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/fastscroll_label_right_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/fastscroll_thumb_default_holo.png b/core/res/res/drawable-xhdpi/fastscroll_thumb_default_holo.png
index 98404d4..35c78ac 100644
--- a/core/res/res/drawable-xhdpi/fastscroll_thumb_default_holo.png
+++ b/core/res/res/drawable-xhdpi/fastscroll_thumb_default_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/fastscroll_thumb_pressed_holo.png b/core/res/res/drawable-xhdpi/fastscroll_thumb_pressed_holo.png
index 6824947..3276b79 100644
--- a/core/res/res/drawable-xhdpi/fastscroll_thumb_pressed_holo.png
+++ b/core/res/res/drawable-xhdpi/fastscroll_thumb_pressed_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/fastscroll_track_default_holo_dark.9.png b/core/res/res/drawable-xhdpi/fastscroll_track_default_holo_dark.9.png
index 751e0d5..752141c 100644
--- a/core/res/res/drawable-xhdpi/fastscroll_track_default_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/fastscroll_track_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/fastscroll_track_default_holo_light.9.png b/core/res/res/drawable-xhdpi/fastscroll_track_default_holo_light.9.png
index 751e0d5..752141c 100644
--- a/core/res/res/drawable-xhdpi/fastscroll_track_default_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/fastscroll_track_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/fastscroll_track_pressed_holo_dark.9.png b/core/res/res/drawable-xhdpi/fastscroll_track_pressed_holo_dark.9.png
index c9427a9..0173ada 100644
--- a/core/res/res/drawable-xhdpi/fastscroll_track_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/fastscroll_track_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/fastscroll_track_pressed_holo_light.9.png b/core/res/res/drawable-xhdpi/fastscroll_track_pressed_holo_light.9.png
index b495fbd..d489b8d 100644
--- a/core/res/res/drawable-xhdpi/fastscroll_track_pressed_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/fastscroll_track_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/focused_application_background_static.png b/core/res/res/drawable-xhdpi/focused_application_background_static.png
index 8231e4f..0c29cc4 100644
--- a/core/res/res/drawable-xhdpi/focused_application_background_static.png
+++ b/core/res/res/drawable-xhdpi/focused_application_background_static.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/frame_gallery_thumb.9.png b/core/res/res/drawable-xhdpi/frame_gallery_thumb.9.png
index a6bb25a..a2665da 100644
--- a/core/res/res/drawable-xhdpi/frame_gallery_thumb.9.png
+++ b/core/res/res/drawable-xhdpi/frame_gallery_thumb.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/frame_gallery_thumb_pressed.9.png b/core/res/res/drawable-xhdpi/frame_gallery_thumb_pressed.9.png
index 85d65faa71..0b93dd6 100644
--- a/core/res/res/drawable-xhdpi/frame_gallery_thumb_pressed.9.png
+++ b/core/res/res/drawable-xhdpi/frame_gallery_thumb_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/frame_gallery_thumb_selected.9.png b/core/res/res/drawable-xhdpi/frame_gallery_thumb_selected.9.png
index 1dadee6..c4f25b3 100644
--- a/core/res/res/drawable-xhdpi/frame_gallery_thumb_selected.9.png
+++ b/core/res/res/drawable-xhdpi/frame_gallery_thumb_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/gallery_selected_default.9.png b/core/res/res/drawable-xhdpi/gallery_selected_default.9.png
index 742492a..a8f70bb 100644
--- a/core/res/res/drawable-xhdpi/gallery_selected_default.9.png
+++ b/core/res/res/drawable-xhdpi/gallery_selected_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/gallery_selected_focused.9.png b/core/res/res/drawable-xhdpi/gallery_selected_focused.9.png
index 4f5700f..e1b847b 100644
--- a/core/res/res/drawable-xhdpi/gallery_selected_focused.9.png
+++ b/core/res/res/drawable-xhdpi/gallery_selected_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/gallery_selected_pressed.9.png b/core/res/res/drawable-xhdpi/gallery_selected_pressed.9.png
index 00b36b8..740eb35 100644
--- a/core/res/res/drawable-xhdpi/gallery_selected_pressed.9.png
+++ b/core/res/res/drawable-xhdpi/gallery_selected_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/gallery_unselected_default.9.png b/core/res/res/drawable-xhdpi/gallery_unselected_default.9.png
index 9bc0cdb..000b5af 100644
--- a/core/res/res/drawable-xhdpi/gallery_unselected_default.9.png
+++ b/core/res/res/drawable-xhdpi/gallery_unselected_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/gallery_unselected_pressed.9.png b/core/res/res/drawable-xhdpi/gallery_unselected_pressed.9.png
index c10554a..f7d61830 100644
--- a/core/res/res/drawable-xhdpi/gallery_unselected_pressed.9.png
+++ b/core/res/res/drawable-xhdpi/gallery_unselected_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/grid_selector_background_focus.9.png b/core/res/res/drawable-xhdpi/grid_selector_background_focus.9.png
index bafc62a..55d89f8 100644
--- a/core/res/res/drawable-xhdpi/grid_selector_background_focus.9.png
+++ b/core/res/res/drawable-xhdpi/grid_selector_background_focus.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/grid_selector_background_pressed.9.png b/core/res/res/drawable-xhdpi/grid_selector_background_pressed.9.png
index 40e8a0e..9b45494 100644
--- a/core/res/res/drawable-xhdpi/grid_selector_background_pressed.9.png
+++ b/core/res/res/drawable-xhdpi/grid_selector_background_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/highlight_disabled.9.png b/core/res/res/drawable-xhdpi/highlight_disabled.9.png
index a65fe8f..bc11a22 100644
--- a/core/res/res/drawable-xhdpi/highlight_disabled.9.png
+++ b/core/res/res/drawable-xhdpi/highlight_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/highlight_pressed.9.png b/core/res/res/drawable-xhdpi/highlight_pressed.9.png
index d0e1564..32e6a35 100644
--- a/core/res/res/drawable-xhdpi/highlight_pressed.9.png
+++ b/core/res/res/drawable-xhdpi/highlight_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/highlight_selected.9.png b/core/res/res/drawable-xhdpi/highlight_selected.9.png
index d332ee6..2a2eaa5 100644
--- a/core/res/res/drawable-xhdpi/highlight_selected.9.png
+++ b/core/res/res/drawable-xhdpi/highlight_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_ab_back_holo_dark_am.png b/core/res/res/drawable-xhdpi/ic_ab_back_holo_dark_am.png
index 8ded62f..6dc2a13 100644
--- a/core/res/res/drawable-xhdpi/ic_ab_back_holo_dark_am.png
+++ b/core/res/res/drawable-xhdpi/ic_ab_back_holo_dark_am.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_ab_back_holo_light_am.png b/core/res/res/drawable-xhdpi/ic_ab_back_holo_light_am.png
index 517e9f7..892763e 100644
--- a/core/res/res/drawable-xhdpi/ic_ab_back_holo_light_am.png
+++ b/core/res/res/drawable-xhdpi/ic_ab_back_holo_light_am.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_aggregated.png b/core/res/res/drawable-xhdpi/ic_aggregated.png
index 818a1b1..39873ae 100644
--- a/core/res/res/drawable-xhdpi/ic_aggregated.png
+++ b/core/res/res/drawable-xhdpi/ic_aggregated.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_audio_notification_am_alpha.png b/core/res/res/drawable-xhdpi/ic_audio_notification_am_alpha.png
index 15182b9..9465f68 100644
--- a/core/res/res/drawable-xhdpi/ic_audio_notification_am_alpha.png
+++ b/core/res/res/drawable-xhdpi/ic_audio_notification_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_audio_notification_mute_am_alpha.png b/core/res/res/drawable-xhdpi/ic_audio_notification_mute_am_alpha.png
index c26b839..9727b07 100644
--- a/core/res/res/drawable-xhdpi/ic_audio_notification_mute_am_alpha.png
+++ b/core/res/res/drawable-xhdpi/ic_audio_notification_mute_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_btn_round_more_disabled.png b/core/res/res/drawable-xhdpi/ic_btn_round_more_disabled.png
index 99f37c5..73495ef 100644
--- a/core/res/res/drawable-xhdpi/ic_btn_round_more_disabled.png
+++ b/core/res/res/drawable-xhdpi/ic_btn_round_more_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_btn_round_more_normal.png b/core/res/res/drawable-xhdpi/ic_btn_round_more_normal.png
index 7a8221f..3187293 100644
--- a/core/res/res/drawable-xhdpi/ic_btn_round_more_normal.png
+++ b/core/res/res/drawable-xhdpi/ic_btn_round_more_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_btn_search_go.png b/core/res/res/drawable-xhdpi/ic_btn_search_go.png
index 896dddd..34383d9 100644
--- a/core/res/res/drawable-xhdpi/ic_btn_search_go.png
+++ b/core/res/res/drawable-xhdpi/ic_btn_search_go.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_btn_speak_now.png b/core/res/res/drawable-xhdpi/ic_btn_speak_now.png
index f7f4922..21331aa 100644
--- a/core/res/res/drawable-xhdpi/ic_btn_speak_now.png
+++ b/core/res/res/drawable-xhdpi/ic_btn_speak_now.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_btn_square_browser_zoom_fit_page_disabled.png b/core/res/res/drawable-xhdpi/ic_btn_square_browser_zoom_fit_page_disabled.png
index 299a7bf..230b2dd 100644
--- a/core/res/res/drawable-xhdpi/ic_btn_square_browser_zoom_fit_page_disabled.png
+++ b/core/res/res/drawable-xhdpi/ic_btn_square_browser_zoom_fit_page_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_btn_square_browser_zoom_fit_page_normal.png b/core/res/res/drawable-xhdpi/ic_btn_square_browser_zoom_fit_page_normal.png
index c43c68c..f394762 100644
--- a/core/res/res/drawable-xhdpi/ic_btn_square_browser_zoom_fit_page_normal.png
+++ b/core/res/res/drawable-xhdpi/ic_btn_square_browser_zoom_fit_page_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_btn_square_browser_zoom_page_overview_disabled.png b/core/res/res/drawable-xhdpi/ic_btn_square_browser_zoom_page_overview_disabled.png
index fa94bff..7c2f9fd 100644
--- a/core/res/res/drawable-xhdpi/ic_btn_square_browser_zoom_page_overview_disabled.png
+++ b/core/res/res/drawable-xhdpi/ic_btn_square_browser_zoom_page_overview_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_btn_square_browser_zoom_page_overview_normal.png b/core/res/res/drawable-xhdpi/ic_btn_square_browser_zoom_page_overview_normal.png
index 1629d64..50bd1ca 100644
--- a/core/res/res/drawable-xhdpi/ic_btn_square_browser_zoom_page_overview_normal.png
+++ b/core/res/res/drawable-xhdpi/ic_btn_square_browser_zoom_page_overview_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_bullet_key_permission.png b/core/res/res/drawable-xhdpi/ic_bullet_key_permission.png
index 6a0bdfc..8235c38 100644
--- a/core/res/res/drawable-xhdpi/ic_bullet_key_permission.png
+++ b/core/res/res/drawable-xhdpi/ic_bullet_key_permission.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_cab_done_holo.png b/core/res/res/drawable-xhdpi/ic_cab_done_holo.png
index 4eeee43..8796137 100644
--- a/core/res/res/drawable-xhdpi/ic_cab_done_holo.png
+++ b/core/res/res/drawable-xhdpi/ic_cab_done_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_cab_done_holo_dark.png b/core/res/res/drawable-xhdpi/ic_cab_done_holo_dark.png
index 2e06dd0..875fcb0 100644
--- a/core/res/res/drawable-xhdpi/ic_cab_done_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/ic_cab_done_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_cab_done_holo_light.png b/core/res/res/drawable-xhdpi/ic_cab_done_holo_light.png
index bb19810..2c35873 100644
--- a/core/res/res/drawable-xhdpi/ic_cab_done_holo_light.png
+++ b/core/res/res/drawable-xhdpi/ic_cab_done_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_cab_done_mtrl_alpha.png b/core/res/res/drawable-xhdpi/ic_cab_done_mtrl_alpha.png
index 3d6d734..e8db440 100644
--- a/core/res/res/drawable-xhdpi/ic_cab_done_mtrl_alpha.png
+++ b/core/res/res/drawable-xhdpi/ic_cab_done_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_checkmark_holo_light.png b/core/res/res/drawable-xhdpi/ic_checkmark_holo_light.png
index 1607f35..805cc9e 100644
--- a/core/res/res/drawable-xhdpi/ic_checkmark_holo_light.png
+++ b/core/res/res/drawable-xhdpi/ic_checkmark_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_clear_disabled.png b/core/res/res/drawable-xhdpi/ic_clear_disabled.png
index e35c5f0..e2e340b 100644
--- a/core/res/res/drawable-xhdpi/ic_clear_disabled.png
+++ b/core/res/res/drawable-xhdpi/ic_clear_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_clear_search_api_disabled_holo_dark.png b/core/res/res/drawable-xhdpi/ic_clear_search_api_disabled_holo_dark.png
index 272e34a..1971328 100644
--- a/core/res/res/drawable-xhdpi/ic_clear_search_api_disabled_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/ic_clear_search_api_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_clear_search_api_disabled_holo_light.png b/core/res/res/drawable-xhdpi/ic_clear_search_api_disabled_holo_light.png
index 7fd7aeb..ce08bf5 100644
--- a/core/res/res/drawable-xhdpi/ic_clear_search_api_disabled_holo_light.png
+++ b/core/res/res/drawable-xhdpi/ic_clear_search_api_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_clear_search_api_holo_dark.png b/core/res/res/drawable-xhdpi/ic_clear_search_api_holo_dark.png
index 81da970..d7a399d 100644
--- a/core/res/res/drawable-xhdpi/ic_clear_search_api_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/ic_clear_search_api_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_clear_search_api_holo_light.png b/core/res/res/drawable-xhdpi/ic_clear_search_api_holo_light.png
index 53cfbd3..11a25b6 100644
--- a/core/res/res/drawable-xhdpi/ic_clear_search_api_holo_light.png
+++ b/core/res/res/drawable-xhdpi/ic_clear_search_api_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_coins_l.png b/core/res/res/drawable-xhdpi/ic_coins_l.png
index 84e7e72..6e219e6 100644
--- a/core/res/res/drawable-xhdpi/ic_coins_l.png
+++ b/core/res/res/drawable-xhdpi/ic_coins_l.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_coins_s.png b/core/res/res/drawable-xhdpi/ic_coins_s.png
index 13d134e..651e90d 100644
--- a/core/res/res/drawable-xhdpi/ic_coins_s.png
+++ b/core/res/res/drawable-xhdpi/ic_coins_s.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_commit.png b/core/res/res/drawable-xhdpi/ic_commit.png
index b871f7e..4f26456 100644
--- a/core/res/res/drawable-xhdpi/ic_commit.png
+++ b/core/res/res/drawable-xhdpi/ic_commit.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_commit_search_api_holo_dark.png b/core/res/res/drawable-xhdpi/ic_commit_search_api_holo_dark.png
index d8faf90..0f4a24a 100644
--- a/core/res/res/drawable-xhdpi/ic_commit_search_api_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/ic_commit_search_api_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_commit_search_api_holo_light.png b/core/res/res/drawable-xhdpi/ic_commit_search_api_holo_light.png
index e7c7280..3481c99 100644
--- a/core/res/res/drawable-xhdpi/ic_commit_search_api_holo_light.png
+++ b/core/res/res/drawable-xhdpi/ic_commit_search_api_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_commit_search_api_mtrl_alpha.png b/core/res/res/drawable-xhdpi/ic_commit_search_api_mtrl_alpha.png
index c10a1b7..443f0d6 100644
--- a/core/res/res/drawable-xhdpi/ic_commit_search_api_mtrl_alpha.png
+++ b/core/res/res/drawable-xhdpi/ic_commit_search_api_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_contact_picture.png b/core/res/res/drawable-xhdpi/ic_contact_picture.png
index bdba57b..049e2dc 100644
--- a/core/res/res/drawable-xhdpi/ic_contact_picture.png
+++ b/core/res/res/drawable-xhdpi/ic_contact_picture.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_contact_picture_2.png b/core/res/res/drawable-xhdpi/ic_contact_picture_2.png
index ecb7b67..409f647 100644
--- a/core/res/res/drawable-xhdpi/ic_contact_picture_2.png
+++ b/core/res/res/drawable-xhdpi/ic_contact_picture_2.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_contact_picture_3.png b/core/res/res/drawable-xhdpi/ic_contact_picture_3.png
index 326f2f8..2493221 100644
--- a/core/res/res/drawable-xhdpi/ic_contact_picture_3.png
+++ b/core/res/res/drawable-xhdpi/ic_contact_picture_3.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_delete.png b/core/res/res/drawable-xhdpi/ic_delete.png
index 9abc51a..1b7e875 100644
--- a/core/res/res/drawable-xhdpi/ic_delete.png
+++ b/core/res/res/drawable-xhdpi/ic_delete.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_dialog_alert.png b/core/res/res/drawable-xhdpi/ic_dialog_alert.png
index 2834f35..e978405 100644
--- a/core/res/res/drawable-xhdpi/ic_dialog_alert.png
+++ b/core/res/res/drawable-xhdpi/ic_dialog_alert.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_dialog_alert_holo_dark.png b/core/res/res/drawable-xhdpi/ic_dialog_alert_holo_dark.png
index f906e2a..b98d682 100644
--- a/core/res/res/drawable-xhdpi/ic_dialog_alert_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/ic_dialog_alert_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_dialog_alert_holo_light.png b/core/res/res/drawable-xhdpi/ic_dialog_alert_holo_light.png
index a99f062..e3822ae 100644
--- a/core/res/res/drawable-xhdpi/ic_dialog_alert_holo_light.png
+++ b/core/res/res/drawable-xhdpi/ic_dialog_alert_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_dialog_close_normal_holo.png b/core/res/res/drawable-xhdpi/ic_dialog_close_normal_holo.png
index ea3bb48..177c5d4 100644
--- a/core/res/res/drawable-xhdpi/ic_dialog_close_normal_holo.png
+++ b/core/res/res/drawable-xhdpi/ic_dialog_close_normal_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_dialog_close_pressed_holo.png b/core/res/res/drawable-xhdpi/ic_dialog_close_pressed_holo.png
index 5475ef9..6ee8500 100644
--- a/core/res/res/drawable-xhdpi/ic_dialog_close_pressed_holo.png
+++ b/core/res/res/drawable-xhdpi/ic_dialog_close_pressed_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_dialog_dialer.png b/core/res/res/drawable-xhdpi/ic_dialog_dialer.png
index 18f6880..66b25d9 100644
--- a/core/res/res/drawable-xhdpi/ic_dialog_dialer.png
+++ b/core/res/res/drawable-xhdpi/ic_dialog_dialer.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_dialog_email.png b/core/res/res/drawable-xhdpi/ic_dialog_email.png
index 1c1eae6..8910669 100644
--- a/core/res/res/drawable-xhdpi/ic_dialog_email.png
+++ b/core/res/res/drawable-xhdpi/ic_dialog_email.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_dialog_focused_holo.png b/core/res/res/drawable-xhdpi/ic_dialog_focused_holo.png
index 000d885..c75c35b 100644
--- a/core/res/res/drawable-xhdpi/ic_dialog_focused_holo.png
+++ b/core/res/res/drawable-xhdpi/ic_dialog_focused_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_dialog_info.png b/core/res/res/drawable-xhdpi/ic_dialog_info.png
index 478dcc1..f798253 100644
--- a/core/res/res/drawable-xhdpi/ic_dialog_info.png
+++ b/core/res/res/drawable-xhdpi/ic_dialog_info.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_dialog_map.png b/core/res/res/drawable-xhdpi/ic_dialog_map.png
index e25b819..d3030b5 100644
--- a/core/res/res/drawable-xhdpi/ic_dialog_map.png
+++ b/core/res/res/drawable-xhdpi/ic_dialog_map.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_dialog_time.png b/core/res/res/drawable-xhdpi/ic_dialog_time.png
index 10c9d72..bb05d37 100644
--- a/core/res/res/drawable-xhdpi/ic_dialog_time.png
+++ b/core/res/res/drawable-xhdpi/ic_dialog_time.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_dialog_usb.png b/core/res/res/drawable-xhdpi/ic_dialog_usb.png
index 5893bff..ae66484 100644
--- a/core/res/res/drawable-xhdpi/ic_dialog_usb.png
+++ b/core/res/res/drawable-xhdpi/ic_dialog_usb.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_emergency.png b/core/res/res/drawable-xhdpi/ic_emergency.png
index 0e97549..6916baa 100644
--- a/core/res/res/drawable-xhdpi/ic_emergency.png
+++ b/core/res/res/drawable-xhdpi/ic_emergency.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_find_next_holo_dark.png b/core/res/res/drawable-xhdpi/ic_find_next_holo_dark.png
index e8226053..83729b3 100644
--- a/core/res/res/drawable-xhdpi/ic_find_next_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/ic_find_next_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_find_next_holo_light.png b/core/res/res/drawable-xhdpi/ic_find_next_holo_light.png
index 5b6890d..e8688a2 100644
--- a/core/res/res/drawable-xhdpi/ic_find_next_holo_light.png
+++ b/core/res/res/drawable-xhdpi/ic_find_next_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_find_next_mtrl_alpha.png b/core/res/res/drawable-xhdpi/ic_find_next_mtrl_alpha.png
index 9038282..c854ea0 100644
--- a/core/res/res/drawable-xhdpi/ic_find_next_mtrl_alpha.png
+++ b/core/res/res/drawable-xhdpi/ic_find_next_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_find_previous_holo_dark.png b/core/res/res/drawable-xhdpi/ic_find_previous_holo_dark.png
index 0ba45876c..ce84e25 100644
--- a/core/res/res/drawable-xhdpi/ic_find_previous_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/ic_find_previous_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_find_previous_holo_light.png b/core/res/res/drawable-xhdpi/ic_find_previous_holo_light.png
index 73976c7..64b5b94 100644
--- a/core/res/res/drawable-xhdpi/ic_find_previous_holo_light.png
+++ b/core/res/res/drawable-xhdpi/ic_find_previous_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_find_previous_mtrl_alpha.png b/core/res/res/drawable-xhdpi/ic_find_previous_mtrl_alpha.png
index 579347f..1dfe0a5 100644
--- a/core/res/res/drawable-xhdpi/ic_find_previous_mtrl_alpha.png
+++ b/core/res/res/drawable-xhdpi/ic_find_previous_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_go.png b/core/res/res/drawable-xhdpi/ic_go.png
index 1e2dcfa..af547c7 100644
--- a/core/res/res/drawable-xhdpi/ic_go.png
+++ b/core/res/res/drawable-xhdpi/ic_go.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_go_search_api_holo_dark.png b/core/res/res/drawable-xhdpi/ic_go_search_api_holo_dark.png
index 0d0758c..2cbef6a 100644
--- a/core/res/res/drawable-xhdpi/ic_go_search_api_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/ic_go_search_api_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_go_search_api_holo_light.png b/core/res/res/drawable-xhdpi/ic_go_search_api_holo_light.png
index f12eafc..666df17 100644
--- a/core/res/res/drawable-xhdpi/ic_go_search_api_holo_light.png
+++ b/core/res/res/drawable-xhdpi/ic_go_search_api_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_input_add.png b/core/res/res/drawable-xhdpi/ic_input_add.png
index f1242f5..165dd64 100644
--- a/core/res/res/drawable-xhdpi/ic_input_add.png
+++ b/core/res/res/drawable-xhdpi/ic_input_add.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_input_delete.png b/core/res/res/drawable-xhdpi/ic_input_delete.png
index 8b822d9..c1887c0 100644
--- a/core/res/res/drawable-xhdpi/ic_input_delete.png
+++ b/core/res/res/drawable-xhdpi/ic_input_delete.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_input_get.png b/core/res/res/drawable-xhdpi/ic_input_get.png
index 7f9e9bf..6c0f49b 100644
--- a/core/res/res/drawable-xhdpi/ic_input_get.png
+++ b/core/res/res/drawable-xhdpi/ic_input_get.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_jog_dial_answer.png b/core/res/res/drawable-xhdpi/ic_jog_dial_answer.png
index eedb7fd..12d9710 100644
--- a/core/res/res/drawable-xhdpi/ic_jog_dial_answer.png
+++ b/core/res/res/drawable-xhdpi/ic_jog_dial_answer.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_jog_dial_answer_and_end.png b/core/res/res/drawable-xhdpi/ic_jog_dial_answer_and_end.png
index 829973e..5b2327f 100644
--- a/core/res/res/drawable-xhdpi/ic_jog_dial_answer_and_end.png
+++ b/core/res/res/drawable-xhdpi/ic_jog_dial_answer_and_end.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_jog_dial_answer_and_hold.png b/core/res/res/drawable-xhdpi/ic_jog_dial_answer_and_hold.png
index e8336d0..ef2bda7 100644
--- a/core/res/res/drawable-xhdpi/ic_jog_dial_answer_and_hold.png
+++ b/core/res/res/drawable-xhdpi/ic_jog_dial_answer_and_hold.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_jog_dial_decline.png b/core/res/res/drawable-xhdpi/ic_jog_dial_decline.png
index 7cab5f5..bae0ef1 100644
--- a/core/res/res/drawable-xhdpi/ic_jog_dial_decline.png
+++ b/core/res/res/drawable-xhdpi/ic_jog_dial_decline.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_jog_dial_sound_off.png b/core/res/res/drawable-xhdpi/ic_jog_dial_sound_off.png
index 65aa39b..2db2d95 100644
--- a/core/res/res/drawable-xhdpi/ic_jog_dial_sound_off.png
+++ b/core/res/res/drawable-xhdpi/ic_jog_dial_sound_off.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_jog_dial_sound_on.png b/core/res/res/drawable-xhdpi/ic_jog_dial_sound_on.png
index ce8f3a7..0bf18a1 100644
--- a/core/res/res/drawable-xhdpi/ic_jog_dial_sound_on.png
+++ b/core/res/res/drawable-xhdpi/ic_jog_dial_sound_on.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_jog_dial_unlock.png b/core/res/res/drawable-xhdpi/ic_jog_dial_unlock.png
index 5d6fb7b..66164ba 100644
--- a/core/res/res/drawable-xhdpi/ic_jog_dial_unlock.png
+++ b/core/res/res/drawable-xhdpi/ic_jog_dial_unlock.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_jog_dial_vibrate_on.png b/core/res/res/drawable-xhdpi/ic_jog_dial_vibrate_on.png
index 6fe8b77..913893b 100644
--- a/core/res/res/drawable-xhdpi/ic_jog_dial_vibrate_on.png
+++ b/core/res/res/drawable-xhdpi/ic_jog_dial_vibrate_on.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_launcher_android.png b/core/res/res/drawable-xhdpi/ic_launcher_android.png
index 824794a..f38d05b 100644
--- a/core/res/res/drawable-xhdpi/ic_launcher_android.png
+++ b/core/res/res/drawable-xhdpi/ic_launcher_android.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lock_airplane_mode_alpha.png b/core/res/res/drawable-xhdpi/ic_lock_airplane_mode_alpha.png
index dc7a917..d877a7f 100644
--- a/core/res/res/drawable-xhdpi/ic_lock_airplane_mode_alpha.png
+++ b/core/res/res/drawable-xhdpi/ic_lock_airplane_mode_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lock_airplane_mode_off_am_alpha.png b/core/res/res/drawable-xhdpi/ic_lock_airplane_mode_off_am_alpha.png
index 497ca2b..1d5a39b 100644
--- a/core/res/res/drawable-xhdpi/ic_lock_airplane_mode_off_am_alpha.png
+++ b/core/res/res/drawable-xhdpi/ic_lock_airplane_mode_off_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lock_idle_alarm_alpha.png b/core/res/res/drawable-xhdpi/ic_lock_idle_alarm_alpha.png
index 2822a92..e9bb6d6 100644
--- a/core/res/res/drawable-xhdpi/ic_lock_idle_alarm_alpha.png
+++ b/core/res/res/drawable-xhdpi/ic_lock_idle_alarm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lock_idle_charging.png b/core/res/res/drawable-xhdpi/ic_lock_idle_charging.png
index 14c8da4..72e0c9f 100644
--- a/core/res/res/drawable-xhdpi/ic_lock_idle_charging.png
+++ b/core/res/res/drawable-xhdpi/ic_lock_idle_charging.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lock_idle_lock.png b/core/res/res/drawable-xhdpi/ic_lock_idle_lock.png
index 38b6786..180a388 100644
--- a/core/res/res/drawable-xhdpi/ic_lock_idle_lock.png
+++ b/core/res/res/drawable-xhdpi/ic_lock_idle_lock.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lock_idle_low_battery.png b/core/res/res/drawable-xhdpi/ic_lock_idle_low_battery.png
index 19af7e9..e012667 100644
--- a/core/res/res/drawable-xhdpi/ic_lock_idle_low_battery.png
+++ b/core/res/res/drawable-xhdpi/ic_lock_idle_low_battery.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lock_lock_alpha.png b/core/res/res/drawable-xhdpi/ic_lock_lock_alpha.png
index 086a0ca..285754e 100644
--- a/core/res/res/drawable-xhdpi/ic_lock_lock_alpha.png
+++ b/core/res/res/drawable-xhdpi/ic_lock_lock_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lock_open_wht_24dp.png b/core/res/res/drawable-xhdpi/ic_lock_open_wht_24dp.png
index 21d4d53..09defe4 100644
--- a/core/res/res/drawable-xhdpi/ic_lock_open_wht_24dp.png
+++ b/core/res/res/drawable-xhdpi/ic_lock_open_wht_24dp.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lock_outline_wht_24dp.png b/core/res/res/drawable-xhdpi/ic_lock_outline_wht_24dp.png
index 2aeb9a2..33f98a8 100644
--- a/core/res/res/drawable-xhdpi/ic_lock_outline_wht_24dp.png
+++ b/core/res/res/drawable-xhdpi/ic_lock_outline_wht_24dp.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lock_power_off_alpha.png b/core/res/res/drawable-xhdpi/ic_lock_power_off_alpha.png
index 530236c..2a3a059 100644
--- a/core/res/res/drawable-xhdpi/ic_lock_power_off_alpha.png
+++ b/core/res/res/drawable-xhdpi/ic_lock_power_off_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lock_ringer_off_alpha.png b/core/res/res/drawable-xhdpi/ic_lock_ringer_off_alpha.png
index dff2c89..ae74234 100644
--- a/core/res/res/drawable-xhdpi/ic_lock_ringer_off_alpha.png
+++ b/core/res/res/drawable-xhdpi/ic_lock_ringer_off_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lock_ringer_on_alpha.png b/core/res/res/drawable-xhdpi/ic_lock_ringer_on_alpha.png
index 98341b0..8235ab8 100644
--- a/core/res/res/drawable-xhdpi/ic_lock_ringer_on_alpha.png
+++ b/core/res/res/drawable-xhdpi/ic_lock_ringer_on_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lock_silent_mode.png b/core/res/res/drawable-xhdpi/ic_lock_silent_mode.png
index 1ef944f..63f8e24 100644
--- a/core/res/res/drawable-xhdpi/ic_lock_silent_mode.png
+++ b/core/res/res/drawable-xhdpi/ic_lock_silent_mode.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lock_silent_mode_off.png b/core/res/res/drawable-xhdpi/ic_lock_silent_mode_off.png
index 8fd4a57..a8d4d27 100644
--- a/core/res/res/drawable-xhdpi/ic_lock_silent_mode_off.png
+++ b/core/res/res/drawable-xhdpi/ic_lock_silent_mode_off.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lock_silent_mode_vibrate.png b/core/res/res/drawable-xhdpi/ic_lock_silent_mode_vibrate.png
index 921f74e..23f85bd 100644
--- a/core/res/res/drawable-xhdpi/ic_lock_silent_mode_vibrate.png
+++ b/core/res/res/drawable-xhdpi/ic_lock_silent_mode_vibrate.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_handle_pressed.png b/core/res/res/drawable-xhdpi/ic_lockscreen_handle_pressed.png
index 2d28009..2d230cd 100644
--- a/core/res/res/drawable-xhdpi/ic_lockscreen_handle_pressed.png
+++ b/core/res/res/drawable-xhdpi/ic_lockscreen_handle_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_maps_indicator_current_position.png b/core/res/res/drawable-xhdpi/ic_maps_indicator_current_position.png
index 6e2e6cb..3a19dd4 100644
--- a/core/res/res/drawable-xhdpi/ic_maps_indicator_current_position.png
+++ b/core/res/res/drawable-xhdpi/ic_maps_indicator_current_position.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_maps_indicator_current_position_anim1.png b/core/res/res/drawable-xhdpi/ic_maps_indicator_current_position_anim1.png
index 238a8d9..faf65e5 100644
--- a/core/res/res/drawable-xhdpi/ic_maps_indicator_current_position_anim1.png
+++ b/core/res/res/drawable-xhdpi/ic_maps_indicator_current_position_anim1.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_maps_indicator_current_position_anim2.png b/core/res/res/drawable-xhdpi/ic_maps_indicator_current_position_anim2.png
index e69d878..841f051 100644
--- a/core/res/res/drawable-xhdpi/ic_maps_indicator_current_position_anim2.png
+++ b/core/res/res/drawable-xhdpi/ic_maps_indicator_current_position_anim2.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_maps_indicator_current_position_anim3.png b/core/res/res/drawable-xhdpi/ic_maps_indicator_current_position_anim3.png
index 2c362f0..b5ce7e4 100644
--- a/core/res/res/drawable-xhdpi/ic_maps_indicator_current_position_anim3.png
+++ b/core/res/res/drawable-xhdpi/ic_maps_indicator_current_position_anim3.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_embed_play.png b/core/res/res/drawable-xhdpi/ic_media_embed_play.png
index b26f565..dcec4e3 100644
--- a/core/res/res/drawable-xhdpi/ic_media_embed_play.png
+++ b/core/res/res/drawable-xhdpi/ic_media_embed_play.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_ff.png b/core/res/res/drawable-xhdpi/ic_media_ff.png
index 60f7e92..f562622 100644
--- a/core/res/res/drawable-xhdpi/ic_media_ff.png
+++ b/core/res/res/drawable-xhdpi/ic_media_ff.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_fullscreen.png b/core/res/res/drawable-xhdpi/ic_media_fullscreen.png
index 9526218..62d9a46 100644
--- a/core/res/res/drawable-xhdpi/ic_media_fullscreen.png
+++ b/core/res/res/drawable-xhdpi/ic_media_fullscreen.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_next.png b/core/res/res/drawable-xhdpi/ic_media_next.png
index 4def965..b1f2bb3 100644
--- a/core/res/res/drawable-xhdpi/ic_media_next.png
+++ b/core/res/res/drawable-xhdpi/ic_media_next.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_pause.png b/core/res/res/drawable-xhdpi/ic_media_pause.png
index 6bd3d48..ad7f6b1 100644
--- a/core/res/res/drawable-xhdpi/ic_media_pause.png
+++ b/core/res/res/drawable-xhdpi/ic_media_pause.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_play.png b/core/res/res/drawable-xhdpi/ic_media_play.png
index ccfef18..22b4007 100644
--- a/core/res/res/drawable-xhdpi/ic_media_play.png
+++ b/core/res/res/drawable-xhdpi/ic_media_play.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_previous.png b/core/res/res/drawable-xhdpi/ic_media_previous.png
index c4472ae..87170893 100644
--- a/core/res/res/drawable-xhdpi/ic_media_previous.png
+++ b/core/res/res/drawable-xhdpi/ic_media_previous.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_rew.png b/core/res/res/drawable-xhdpi/ic_media_rew.png
index 167d10e..9c8abc2 100644
--- a/core/res/res/drawable-xhdpi/ic_media_rew.png
+++ b/core/res/res/drawable-xhdpi/ic_media_rew.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_disabled_holo_dark.png b/core/res/res/drawable-xhdpi/ic_media_route_disabled_holo_dark.png
index 4119cff..7511bbd 100644
--- a/core/res/res/drawable-xhdpi/ic_media_route_disabled_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/ic_media_route_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_disabled_holo_light.png b/core/res/res/drawable-xhdpi/ic_media_route_disabled_holo_light.png
index b629a57..d5c5e7b 100644
--- a/core/res/res/drawable-xhdpi/ic_media_route_disabled_holo_light.png
+++ b/core/res/res/drawable-xhdpi/ic_media_route_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_disabled_mtrl_alpha.png b/core/res/res/drawable-xhdpi/ic_media_route_disabled_mtrl_alpha.png
index a020d64..7d69bb2c 100644
--- a/core/res/res/drawable-xhdpi/ic_media_route_disabled_mtrl_alpha.png
+++ b/core/res/res/drawable-xhdpi/ic_media_route_disabled_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_off_dark_mtrl.png b/core/res/res/drawable-xhdpi/ic_media_route_off_dark_mtrl.png
index 1d85b66..efb3211 100644
--- a/core/res/res/drawable-xhdpi/ic_media_route_off_dark_mtrl.png
+++ b/core/res/res/drawable-xhdpi/ic_media_route_off_dark_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_off_holo_dark.png b/core/res/res/drawable-xhdpi/ic_media_route_off_holo_dark.png
index fe81128..2f9e998 100644
--- a/core/res/res/drawable-xhdpi/ic_media_route_off_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/ic_media_route_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_off_holo_light.png b/core/res/res/drawable-xhdpi/ic_media_route_off_holo_light.png
index 9b59eaf..ba0e51c 100644
--- a/core/res/res/drawable-xhdpi/ic_media_route_off_holo_light.png
+++ b/core/res/res/drawable-xhdpi/ic_media_route_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_off_light_mtrl.png b/core/res/res/drawable-xhdpi/ic_media_route_off_light_mtrl.png
index 231aec4..8b4479a 100644
--- a/core/res/res/drawable-xhdpi/ic_media_route_off_light_mtrl.png
+++ b/core/res/res/drawable-xhdpi/ic_media_route_off_light_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_0_holo_dark.png b/core/res/res/drawable-xhdpi/ic_media_route_on_0_holo_dark.png
index 1a513c1..a823a6f 100644
--- a/core/res/res/drawable-xhdpi/ic_media_route_on_0_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_0_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_0_holo_light.png b/core/res/res/drawable-xhdpi/ic_media_route_on_0_holo_light.png
index ff78803..f1c822e 100644
--- a/core/res/res/drawable-xhdpi/ic_media_route_on_0_holo_light.png
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_0_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_1_holo_dark.png b/core/res/res/drawable-xhdpi/ic_media_route_on_1_holo_dark.png
index 4c4b624..b88c29f 100644
--- a/core/res/res/drawable-xhdpi/ic_media_route_on_1_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_1_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_1_holo_light.png b/core/res/res/drawable-xhdpi/ic_media_route_on_1_holo_light.png
index 60f8c4d..3721a38 100644
--- a/core/res/res/drawable-xhdpi/ic_media_route_on_1_holo_light.png
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_1_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_2_holo_dark.png b/core/res/res/drawable-xhdpi/ic_media_route_on_2_holo_dark.png
index cdb2f30..50cf165 100644
--- a/core/res/res/drawable-xhdpi/ic_media_route_on_2_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_2_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_2_holo_light.png b/core/res/res/drawable-xhdpi/ic_media_route_on_2_holo_light.png
index 97a10a3..dec402e 100644
--- a/core/res/res/drawable-xhdpi/ic_media_route_on_2_holo_light.png
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_2_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_holo_dark.png b/core/res/res/drawable-xhdpi/ic_media_route_on_holo_dark.png
index a19a083..e753077 100644
--- a/core/res/res/drawable-xhdpi/ic_media_route_on_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_holo_light.png b/core/res/res/drawable-xhdpi/ic_media_route_on_holo_light.png
index db30613..d53f005 100644
--- a/core/res/res/drawable-xhdpi/ic_media_route_on_holo_light.png
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_stop.png b/core/res/res/drawable-xhdpi/ic_media_stop.png
index 89f36950..8fb3581 100644
--- a/core/res/res/drawable-xhdpi/ic_media_stop.png
+++ b/core/res/res/drawable-xhdpi/ic_media_stop.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_video_poster.png b/core/res/res/drawable-xhdpi/ic_media_video_poster.png
index 4aa4904..5ef732db 100644
--- a/core/res/res/drawable-xhdpi/ic_media_video_poster.png
+++ b/core/res/res/drawable-xhdpi/ic_media_video_poster.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_account_list.png b/core/res/res/drawable-xhdpi/ic_menu_account_list.png
index ebe29b96..ab9a342 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_account_list.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_account_list.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_add.png b/core/res/res/drawable-xhdpi/ic_menu_add.png
index 7d498a9..a279b6f 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_add.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_add.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_agenda.png b/core/res/res/drawable-xhdpi/ic_menu_agenda.png
index 25e9f11..3ed3985 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_agenda.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_agenda.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_allfriends.png b/core/res/res/drawable-xhdpi/ic_menu_allfriends.png
index 20994ed..27ace0e 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_allfriends.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_allfriends.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_always_landscape_portrait.png b/core/res/res/drawable-xhdpi/ic_menu_always_landscape_portrait.png
index 96606de..35f2345 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_always_landscape_portrait.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_always_landscape_portrait.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_archive.png b/core/res/res/drawable-xhdpi/ic_menu_archive.png
index b1be9d5..7e0c959 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_archive.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_archive.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_attachment.png b/core/res/res/drawable-xhdpi/ic_menu_attachment.png
index aa41bd6..bedd151 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_attachment.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_attachment.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_back.png b/core/res/res/drawable-xhdpi/ic_menu_back.png
index 8ac4f64..7b98ab1 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_back.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_back.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_block.png b/core/res/res/drawable-xhdpi/ic_menu_block.png
index e672395..035f598 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_block.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_block.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_blocked_user.png b/core/res/res/drawable-xhdpi/ic_menu_blocked_user.png
index 53a279e..2e38ab0 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_blocked_user.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_blocked_user.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_btn_add.png b/core/res/res/drawable-xhdpi/ic_menu_btn_add.png
index 7d498a9..a279b6f 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_btn_add.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_btn_add.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_call.png b/core/res/res/drawable-xhdpi/ic_menu_call.png
index 703a76b..82e55af 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_call.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_call.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_camera.png b/core/res/res/drawable-xhdpi/ic_menu_camera.png
index 7875aa3..3058bb6 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_camera.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_camera.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_cc_am.png b/core/res/res/drawable-xhdpi/ic_menu_cc_am.png
index 50d686a..5a909fd 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_cc_am.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_cc_am.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_chat_dashboard.png b/core/res/res/drawable-xhdpi/ic_menu_chat_dashboard.png
index c0b238c..a600e40 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_chat_dashboard.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_chat_dashboard.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_clear_playlist.png b/core/res/res/drawable-xhdpi/ic_menu_clear_playlist.png
index 8981d6f..7f487dd 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_clear_playlist.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_clear_playlist.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_close_clear_cancel.png b/core/res/res/drawable-xhdpi/ic_menu_close_clear_cancel.png
index d743d75..74695aa 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_close_clear_cancel.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_close_clear_cancel.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_compass.png b/core/res/res/drawable-xhdpi/ic_menu_compass.png
index 1c2ad89..6c4791c 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_compass.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_compass.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_compose.png b/core/res/res/drawable-xhdpi/ic_menu_compose.png
index bef190e..e9e6061 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_compose.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_compose.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_copy.png b/core/res/res/drawable-xhdpi/ic_menu_copy.png
index 22761fc..5962009 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_copy.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_copy.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_copy_holo_dark.png b/core/res/res/drawable-xhdpi/ic_menu_copy_holo_dark.png
index ba883ae..f6ff46c 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_copy_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_copy_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_copy_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_copy_holo_light.png
index 364b169..b21f131 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_copy_holo_light.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_copy_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_crop.png b/core/res/res/drawable-xhdpi/ic_menu_crop.png
index d32daae..a92f430 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_crop.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_crop.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_cut.png b/core/res/res/drawable-xhdpi/ic_menu_cut.png
index efefcde..2f7dbeaf 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_cut.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_cut.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_cut_holo_dark.png b/core/res/res/drawable-xhdpi/ic_menu_cut_holo_dark.png
index 7aa8750..a05f79b 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_cut_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_cut_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_cut_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_cut_holo_light.png
index d4e4d81..a967065 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_cut_holo_light.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_cut_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_day.png b/core/res/res/drawable-xhdpi/ic_menu_day.png
index 9eed1b2..bcc511a 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_day.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_day.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_delete.png b/core/res/res/drawable-xhdpi/ic_menu_delete.png
index 65b9cae..e008916 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_delete.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_delete.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_directions.png b/core/res/res/drawable-xhdpi/ic_menu_directions.png
index bdc0088..784297d 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_directions.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_directions.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_edit.png b/core/res/res/drawable-xhdpi/ic_menu_edit.png
index fcdd71e..4b917d8 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_edit.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_edit.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_emoticons.png b/core/res/res/drawable-xhdpi/ic_menu_emoticons.png
index af730fa..7922ff0 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_emoticons.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_emoticons.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_end_conversation.png b/core/res/res/drawable-xhdpi/ic_menu_end_conversation.png
index ac76f3b..94cdaf8 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_end_conversation.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_end_conversation.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_find.png b/core/res/res/drawable-xhdpi/ic_menu_find.png
index ccf2aab..6bce9ac 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_find.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_find.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_find_holo_dark.png b/core/res/res/drawable-xhdpi/ic_menu_find_holo_dark.png
index 3ede9e2..e3daa46 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_find_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_find_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_find_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_find_holo_light.png
index de20fa0..ef01aca 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_find_holo_light.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_find_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_find_mtrl_alpha.png b/core/res/res/drawable-xhdpi/ic_menu_find_mtrl_alpha.png
index dd5460f..ef06c61 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_find_mtrl_alpha.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_find_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_forward.png b/core/res/res/drawable-xhdpi/ic_menu_forward.png
index 6463e7a..5d49dce 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_forward.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_forward.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_friendslist.png b/core/res/res/drawable-xhdpi/ic_menu_friendslist.png
index 9200f87..deaaf21 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_friendslist.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_friendslist.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_gallery.png b/core/res/res/drawable-xhdpi/ic_menu_gallery.png
index 6b21e22..03f0ad0 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_gallery.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_gallery.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_goto.png b/core/res/res/drawable-xhdpi/ic_menu_goto.png
index b925e69..607c319 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_goto.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_goto.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_help.png b/core/res/res/drawable-xhdpi/ic_menu_help.png
index 128c7e8..40d42ee 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_help.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_help.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_help_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_help_holo_light.png
index b961de9..61b3468 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_help_holo_light.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_help_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_home.png b/core/res/res/drawable-xhdpi/ic_menu_home.png
index 689f372..5214eb2 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_home.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_home.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_info_details.png b/core/res/res/drawable-xhdpi/ic_menu_info_details.png
index 24ea543..93055c5 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_info_details.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_info_details.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_invite.png b/core/res/res/drawable-xhdpi/ic_menu_invite.png
index d594607..2a9b58d 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_invite.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_invite.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_login.png b/core/res/res/drawable-xhdpi/ic_menu_login.png
index 5095ed9..9fdfd28 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_login.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_login.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_manage.png b/core/res/res/drawable-xhdpi/ic_menu_manage.png
index d7436244..4f7fabe 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_manage.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_manage.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_mapmode.png b/core/res/res/drawable-xhdpi/ic_menu_mapmode.png
index 0b62d08..7c50d5a 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_mapmode.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_mapmode.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_mark.png b/core/res/res/drawable-xhdpi/ic_menu_mark.png
index a5de6fb..96f16b3 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_mark.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_mark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_month.png b/core/res/res/drawable-xhdpi/ic_menu_month.png
index 099263b..b62bbc3 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_month.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_month.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_more.png b/core/res/res/drawable-xhdpi/ic_menu_more.png
index c7a6538..93d7f3a 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_more.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_more.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_moreoverflow.png b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow.png
index 2998d65..8115647 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_moreoverflow.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_focused_holo_dark.png b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_focused_holo_dark.png
index 62659fa..74fe68a 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_focused_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_focused_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_focused_holo_light.png
index 341edaf..c0dd513 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_focused_holo_light.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_dark.png b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_dark.png
index a92fb1d..8163901 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_light.png
index 930ca8d..d4a6f69 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_light.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_my_calendar.png b/core/res/res/drawable-xhdpi/ic_menu_my_calendar.png
index ca95b92..dbd0bdf 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_my_calendar.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_my_calendar.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_mylocation.png b/core/res/res/drawable-xhdpi/ic_menu_mylocation.png
index b0a76a2..2a4ff5c 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_mylocation.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_mylocation.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_myplaces.png b/core/res/res/drawable-xhdpi/ic_menu_myplaces.png
index 205848e..7566b8f 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_myplaces.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_myplaces.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_notifications.png b/core/res/res/drawable-xhdpi/ic_menu_notifications.png
index db80b57..717b808 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_notifications.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_notifications.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_paste.png b/core/res/res/drawable-xhdpi/ic_menu_paste.png
index a69f0eb..66f341e 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_paste.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_paste.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_paste_holo_dark.png b/core/res/res/drawable-xhdpi/ic_menu_paste_holo_dark.png
index 4c5f7f20..3038b69 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_paste_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_paste_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_paste_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_paste_holo_light.png
index 6edd4b2..62b2224 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_paste_holo_light.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_paste_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_play_clip.png b/core/res/res/drawable-xhdpi/ic_menu_play_clip.png
index f680fce..2832081 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_play_clip.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_play_clip.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_preferences.png b/core/res/res/drawable-xhdpi/ic_menu_preferences.png
index 02cfbad..72bbd84 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_preferences.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_preferences.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_recent_history.png b/core/res/res/drawable-xhdpi/ic_menu_recent_history.png
index fc5e1fc..6c2f666 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_recent_history.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_recent_history.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_report_image.png b/core/res/res/drawable-xhdpi/ic_menu_report_image.png
index 26f7ff4..ba2339a 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_report_image.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_report_image.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_revert.png b/core/res/res/drawable-xhdpi/ic_menu_revert.png
index 19c580f..d5baa77 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_revert.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_revert.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_rotate.png b/core/res/res/drawable-xhdpi/ic_menu_rotate.png
index 98e19fe..3f3e3d6 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_rotate.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_rotate.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_save.png b/core/res/res/drawable-xhdpi/ic_menu_save.png
index 62a66d8..f488228 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_save.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_save.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_search.png b/core/res/res/drawable-xhdpi/ic_menu_search.png
index 4444495..8d68fed 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_search.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_search.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_search_holo_dark.png b/core/res/res/drawable-xhdpi/ic_menu_search_holo_dark.png
index 1208859..a3bb40d 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_search_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_search_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_search_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_search_holo_light.png
index 6811782..cd9e2a1 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_search_holo_light.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_search_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_search_mtrl_alpha.png b/core/res/res/drawable-xhdpi/ic_menu_search_mtrl_alpha.png
index 05cfab7..a4776a0 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_search_mtrl_alpha.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_search_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_selectall_holo_dark.png b/core/res/res/drawable-xhdpi/ic_menu_selectall_holo_dark.png
index 8eef37d..b13a82b 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_selectall_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_selectall_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_selectall_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_selectall_holo_light.png
index 2e1cf86..d805942 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_selectall_holo_light.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_selectall_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_send.png b/core/res/res/drawable-xhdpi/ic_menu_send.png
index 6e5ec78..4e8d8e2 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_send.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_send.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_set_as.png b/core/res/res/drawable-xhdpi/ic_menu_set_as.png
index 8689766..e9c1c3f 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_set_as.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_set_as.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_settings_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_settings_holo_light.png
index aa33c38..0b16b48 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_settings_holo_light.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_settings_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_share.png b/core/res/res/drawable-xhdpi/ic_menu_share.png
index fce1d35..f0afa10 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_share.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_share.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_share_holo_dark.png b/core/res/res/drawable-xhdpi/ic_menu_share_holo_dark.png
index 45a0f1d..477f8e1 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_share_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_share_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_share_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_share_holo_light.png
index 528e554..d4c3d7d 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_share_holo_light.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_share_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_slideshow.png b/core/res/res/drawable-xhdpi/ic_menu_slideshow.png
index 8740f37..4f1ce36 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_slideshow.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_slideshow.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_sort_alphabetically.png b/core/res/res/drawable-xhdpi/ic_menu_sort_alphabetically.png
index 5736ff8..c5f54bc 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_sort_alphabetically.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_sort_alphabetically.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_sort_by_size.png b/core/res/res/drawable-xhdpi/ic_menu_sort_by_size.png
index fe3836c..38910e7 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_sort_by_size.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_sort_by_size.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_star.png b/core/res/res/drawable-xhdpi/ic_menu_star.png
index c051020..7a3b7d5 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_star.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_star.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_start_conversation.png b/core/res/res/drawable-xhdpi/ic_menu_start_conversation.png
index d71ed174..5638f47 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_start_conversation.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_start_conversation.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_stop.png b/core/res/res/drawable-xhdpi/ic_menu_stop.png
index 855af11..688c418 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_stop.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_stop.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_today.png b/core/res/res/drawable-xhdpi/ic_menu_today.png
index e9ebc5e..3ef0a586 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_today.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_today.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_upload.png b/core/res/res/drawable-xhdpi/ic_menu_upload.png
index 94d1478..e75a4fe 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_upload.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_upload.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_upload_you_tube.png b/core/res/res/drawable-xhdpi/ic_menu_upload_you_tube.png
index 508c354..4a0f124 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_upload_you_tube.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_upload_you_tube.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_view.png b/core/res/res/drawable-xhdpi/ic_menu_view.png
index e97c30df..d991e5c 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_view.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_view.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_week.png b/core/res/res/drawable-xhdpi/ic_menu_week.png
index 2c3e761..2f79e82 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_week.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_week.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_zoom.png b/core/res/res/drawable-xhdpi/ic_menu_zoom.png
index 858aef5..fde1b0b 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_zoom.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_zoom.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_notification_cast_0.png b/core/res/res/drawable-xhdpi/ic_notification_cast_0.png
index 818c1cd..f3395cd 100644
--- a/core/res/res/drawable-xhdpi/ic_notification_cast_0.png
+++ b/core/res/res/drawable-xhdpi/ic_notification_cast_0.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_notification_cast_1.png b/core/res/res/drawable-xhdpi/ic_notification_cast_1.png
index 2a56e31..a5d816a 100644
--- a/core/res/res/drawable-xhdpi/ic_notification_cast_1.png
+++ b/core/res/res/drawable-xhdpi/ic_notification_cast_1.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_notification_cast_2.png b/core/res/res/drawable-xhdpi/ic_notification_cast_2.png
index 3515a76..13db16c 100644
--- a/core/res/res/drawable-xhdpi/ic_notification_cast_2.png
+++ b/core/res/res/drawable-xhdpi/ic_notification_cast_2.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_notification_clear_all.png b/core/res/res/drawable-xhdpi/ic_notification_clear_all.png
index 5c553cf..b3dfe76 100644
--- a/core/res/res/drawable-xhdpi/ic_notification_clear_all.png
+++ b/core/res/res/drawable-xhdpi/ic_notification_clear_all.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_notification_overlay.9.png b/core/res/res/drawable-xhdpi/ic_notification_overlay.9.png
index a7a8bb3..fc9d839 100644
--- a/core/res/res/drawable-xhdpi/ic_notification_overlay.9.png
+++ b/core/res/res/drawable-xhdpi/ic_notification_overlay.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_partial_secure.png b/core/res/res/drawable-xhdpi/ic_partial_secure.png
index 2dfbb1e..a95661b 100644
--- a/core/res/res/drawable-xhdpi/ic_partial_secure.png
+++ b/core/res/res/drawable-xhdpi/ic_partial_secure.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_popup_disk_full.png b/core/res/res/drawable-xhdpi/ic_popup_disk_full.png
index 4313fdc..fade155 100644
--- a/core/res/res/drawable-xhdpi/ic_popup_disk_full.png
+++ b/core/res/res/drawable-xhdpi/ic_popup_disk_full.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_popup_reminder.png b/core/res/res/drawable-xhdpi/ic_popup_reminder.png
index 4a03a1b..8ccd04c 100644
--- a/core/res/res/drawable-xhdpi/ic_popup_reminder.png
+++ b/core/res/res/drawable-xhdpi/ic_popup_reminder.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_popup_sync_1.png b/core/res/res/drawable-xhdpi/ic_popup_sync_1.png
index 48f8d53..52e38de 100644
--- a/core/res/res/drawable-xhdpi/ic_popup_sync_1.png
+++ b/core/res/res/drawable-xhdpi/ic_popup_sync_1.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_popup_sync_2.png b/core/res/res/drawable-xhdpi/ic_popup_sync_2.png
index 880c202..a069f4b 100644
--- a/core/res/res/drawable-xhdpi/ic_popup_sync_2.png
+++ b/core/res/res/drawable-xhdpi/ic_popup_sync_2.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_popup_sync_3.png b/core/res/res/drawable-xhdpi/ic_popup_sync_3.png
index eb6d03c..4b26817 100644
--- a/core/res/res/drawable-xhdpi/ic_popup_sync_3.png
+++ b/core/res/res/drawable-xhdpi/ic_popup_sync_3.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_popup_sync_4.png b/core/res/res/drawable-xhdpi/ic_popup_sync_4.png
index 02a4d93..6414c66 100644
--- a/core/res/res/drawable-xhdpi/ic_popup_sync_4.png
+++ b/core/res/res/drawable-xhdpi/ic_popup_sync_4.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_popup_sync_5.png b/core/res/res/drawable-xhdpi/ic_popup_sync_5.png
index caaf598..0a8ef8e 100644
--- a/core/res/res/drawable-xhdpi/ic_popup_sync_5.png
+++ b/core/res/res/drawable-xhdpi/ic_popup_sync_5.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_popup_sync_6.png b/core/res/res/drawable-xhdpi/ic_popup_sync_6.png
index e662ab2..d93d7d1 100644
--- a/core/res/res/drawable-xhdpi/ic_popup_sync_6.png
+++ b/core/res/res/drawable-xhdpi/ic_popup_sync_6.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_search.png b/core/res/res/drawable-xhdpi/ic_search.png
index 738a392..cc221d4 100644
--- a/core/res/res/drawable-xhdpi/ic_search.png
+++ b/core/res/res/drawable-xhdpi/ic_search.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_search_api_holo_dark.png b/core/res/res/drawable-xhdpi/ic_search_api_holo_dark.png
index b0d7acf..a57e6c3 100644
--- a/core/res/res/drawable-xhdpi/ic_search_api_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/ic_search_api_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_search_api_holo_light.png b/core/res/res/drawable-xhdpi/ic_search_api_holo_light.png
index c9626a0..78aab7d 100644
--- a/core/res/res/drawable-xhdpi/ic_search_api_holo_light.png
+++ b/core/res/res/drawable-xhdpi/ic_search_api_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_search_category_default.png b/core/res/res/drawable-xhdpi/ic_search_category_default.png
index 351cfe0..0137df27 100644
--- a/core/res/res/drawable-xhdpi/ic_search_category_default.png
+++ b/core/res/res/drawable-xhdpi/ic_search_category_default.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_secure.png b/core/res/res/drawable-xhdpi/ic_secure.png
index 9e24028..6063ffd 100644
--- a/core/res/res/drawable-xhdpi/ic_secure.png
+++ b/core/res/res/drawable-xhdpi/ic_secure.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_settings.png b/core/res/res/drawable-xhdpi/ic_settings.png
index 208089d..43a4b82 100644
--- a/core/res/res/drawable-xhdpi/ic_settings.png
+++ b/core/res/res/drawable-xhdpi/ic_settings.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_settings_language.png b/core/res/res/drawable-xhdpi/ic_settings_language.png
index 2c42db3..97e4943 100644
--- a/core/res/res/drawable-xhdpi/ic_settings_language.png
+++ b/core/res/res/drawable-xhdpi/ic_settings_language.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_sim_card_multi_24px_clr.png b/core/res/res/drawable-xhdpi/ic_sim_card_multi_24px_clr.png
index 9675e56..1648f55 100644
--- a/core/res/res/drawable-xhdpi/ic_sim_card_multi_24px_clr.png
+++ b/core/res/res/drawable-xhdpi/ic_sim_card_multi_24px_clr.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_sim_card_multi_48px_clr.png b/core/res/res/drawable-xhdpi/ic_sim_card_multi_48px_clr.png
index a57a0b9..46b2583 100644
--- a/core/res/res/drawable-xhdpi/ic_sim_card_multi_48px_clr.png
+++ b/core/res/res/drawable-xhdpi/ic_sim_card_multi_48px_clr.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_star_half_black_16dp.png b/core/res/res/drawable-xhdpi/ic_star_half_black_16dp.png
index 5d6f3c8..0751d42 100644
--- a/core/res/res/drawable-xhdpi/ic_star_half_black_16dp.png
+++ b/core/res/res/drawable-xhdpi/ic_star_half_black_16dp.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_star_half_black_36dp.png b/core/res/res/drawable-xhdpi/ic_star_half_black_36dp.png
index 2ed3a20..8381c3a 100644
--- a/core/res/res/drawable-xhdpi/ic_star_half_black_36dp.png
+++ b/core/res/res/drawable-xhdpi/ic_star_half_black_36dp.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_star_half_black_48dp.png b/core/res/res/drawable-xhdpi/ic_star_half_black_48dp.png
index 348d4d84..cdd08ec 100644
--- a/core/res/res/drawable-xhdpi/ic_star_half_black_48dp.png
+++ b/core/res/res/drawable-xhdpi/ic_star_half_black_48dp.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_vibrate.png b/core/res/res/drawable-xhdpi/ic_vibrate.png
index 5d0724a..210aa7d 100644
--- a/core/res/res/drawable-xhdpi/ic_vibrate.png
+++ b/core/res/res/drawable-xhdpi/ic_vibrate.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_vibrate_small.png b/core/res/res/drawable-xhdpi/ic_vibrate_small.png
index 6ee6fd8..8ce6571 100644
--- a/core/res/res/drawable-xhdpi/ic_vibrate_small.png
+++ b/core/res/res/drawable-xhdpi/ic_vibrate_small.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_voice_search.png b/core/res/res/drawable-xhdpi/ic_voice_search.png
index 3f0518b..8d2f57f 100644
--- a/core/res/res/drawable-xhdpi/ic_voice_search.png
+++ b/core/res/res/drawable-xhdpi/ic_voice_search.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_voice_search_api_holo_dark.png b/core/res/res/drawable-xhdpi/ic_voice_search_api_holo_dark.png
index eb6e5fa..bf91495 100644
--- a/core/res/res/drawable-xhdpi/ic_voice_search_api_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/ic_voice_search_api_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_voice_search_api_holo_light.png b/core/res/res/drawable-xhdpi/ic_voice_search_api_holo_light.png
index c6b40bb..6546ca0 100644
--- a/core/res/res/drawable-xhdpi/ic_voice_search_api_holo_light.png
+++ b/core/res/res/drawable-xhdpi/ic_voice_search_api_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_volume.png b/core/res/res/drawable-xhdpi/ic_volume.png
index f6a457d..5062266 100644
--- a/core/res/res/drawable-xhdpi/ic_volume.png
+++ b/core/res/res/drawable-xhdpi/ic_volume.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_volume_bluetooth_ad2p.png b/core/res/res/drawable-xhdpi/ic_volume_bluetooth_ad2p.png
index cbcdf33..dc456bb 100644
--- a/core/res/res/drawable-xhdpi/ic_volume_bluetooth_ad2p.png
+++ b/core/res/res/drawable-xhdpi/ic_volume_bluetooth_ad2p.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_volume_bluetooth_in_call.png b/core/res/res/drawable-xhdpi/ic_volume_bluetooth_in_call.png
index 9c7e906..89f24b7 100644
--- a/core/res/res/drawable-xhdpi/ic_volume_bluetooth_in_call.png
+++ b/core/res/res/drawable-xhdpi/ic_volume_bluetooth_in_call.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_volume_off.png b/core/res/res/drawable-xhdpi/ic_volume_off.png
index e094514..b7448b0 100644
--- a/core/res/res/drawable-xhdpi/ic_volume_off.png
+++ b/core/res/res/drawable-xhdpi/ic_volume_off.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_volume_off_small.png b/core/res/res/drawable-xhdpi/ic_volume_off_small.png
index bc29608..94157e2 100644
--- a/core/res/res/drawable-xhdpi/ic_volume_off_small.png
+++ b/core/res/res/drawable-xhdpi/ic_volume_off_small.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_volume_small.png b/core/res/res/drawable-xhdpi/ic_volume_small.png
index 9d6d920..a9226bc 100644
--- a/core/res/res/drawable-xhdpi/ic_volume_small.png
+++ b/core/res/res/drawable-xhdpi/ic_volume_small.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/icon_highlight_rectangle.9.png b/core/res/res/drawable-xhdpi/icon_highlight_rectangle.9.png
index cdc37f1..31a547f 100644
--- a/core/res/res/drawable-xhdpi/icon_highlight_rectangle.9.png
+++ b/core/res/res/drawable-xhdpi/icon_highlight_rectangle.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/icon_highlight_square.9.png b/core/res/res/drawable-xhdpi/icon_highlight_square.9.png
index cc2ab8c..4750bde 100644
--- a/core/res/res/drawable-xhdpi/icon_highlight_square.9.png
+++ b/core/res/res/drawable-xhdpi/icon_highlight_square.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ime_qwerty.png b/core/res/res/drawable-xhdpi/ime_qwerty.png
index 42c9e5a..6bb73c5 100644
--- a/core/res/res/drawable-xhdpi/ime_qwerty.png
+++ b/core/res/res/drawable-xhdpi/ime_qwerty.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/indicator_input_error.png b/core/res/res/drawable-xhdpi/indicator_input_error.png
index 5be92a0..c2d16aa 100644
--- a/core/res/res/drawable-xhdpi/indicator_input_error.png
+++ b/core/res/res/drawable-xhdpi/indicator_input_error.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/jog_dial_arrow_long_left_green.png b/core/res/res/drawable-xhdpi/jog_dial_arrow_long_left_green.png
index c106f76..11183d3 100644
--- a/core/res/res/drawable-xhdpi/jog_dial_arrow_long_left_green.png
+++ b/core/res/res/drawable-xhdpi/jog_dial_arrow_long_left_green.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/jog_dial_arrow_long_left_yellow.png b/core/res/res/drawable-xhdpi/jog_dial_arrow_long_left_yellow.png
index 7657f74..a01ab93 100644
--- a/core/res/res/drawable-xhdpi/jog_dial_arrow_long_left_yellow.png
+++ b/core/res/res/drawable-xhdpi/jog_dial_arrow_long_left_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/jog_dial_arrow_long_middle_yellow.png b/core/res/res/drawable-xhdpi/jog_dial_arrow_long_middle_yellow.png
index a90926d..77abb90 100644
--- a/core/res/res/drawable-xhdpi/jog_dial_arrow_long_middle_yellow.png
+++ b/core/res/res/drawable-xhdpi/jog_dial_arrow_long_middle_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/jog_dial_arrow_long_right_red.png b/core/res/res/drawable-xhdpi/jog_dial_arrow_long_right_red.png
index 3a00c56..8733536 100644
--- a/core/res/res/drawable-xhdpi/jog_dial_arrow_long_right_red.png
+++ b/core/res/res/drawable-xhdpi/jog_dial_arrow_long_right_red.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/jog_dial_arrow_long_right_yellow.png b/core/res/res/drawable-xhdpi/jog_dial_arrow_long_right_yellow.png
index 113daaa..8dc40c1 100644
--- a/core/res/res/drawable-xhdpi/jog_dial_arrow_long_right_yellow.png
+++ b/core/res/res/drawable-xhdpi/jog_dial_arrow_long_right_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/jog_dial_arrow_short_left.png b/core/res/res/drawable-xhdpi/jog_dial_arrow_short_left.png
index ac62915..40a4879 100644
--- a/core/res/res/drawable-xhdpi/jog_dial_arrow_short_left.png
+++ b/core/res/res/drawable-xhdpi/jog_dial_arrow_short_left.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/jog_dial_arrow_short_left_and_right.png b/core/res/res/drawable-xhdpi/jog_dial_arrow_short_left_and_right.png
index 0efed7a..a05b449 100644
--- a/core/res/res/drawable-xhdpi/jog_dial_arrow_short_left_and_right.png
+++ b/core/res/res/drawable-xhdpi/jog_dial_arrow_short_left_and_right.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/jog_dial_arrow_short_right.png b/core/res/res/drawable-xhdpi/jog_dial_arrow_short_right.png
index 859998b..db45e07 100644
--- a/core/res/res/drawable-xhdpi/jog_dial_arrow_short_right.png
+++ b/core/res/res/drawable-xhdpi/jog_dial_arrow_short_right.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/jog_dial_bg.png b/core/res/res/drawable-xhdpi/jog_dial_bg.png
index 61fcb46..a72c485 100644
--- a/core/res/res/drawable-xhdpi/jog_dial_bg.png
+++ b/core/res/res/drawable-xhdpi/jog_dial_bg.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/jog_dial_dimple.png b/core/res/res/drawable-xhdpi/jog_dial_dimple.png
index 3ab2ab6..f102149 100644
--- a/core/res/res/drawable-xhdpi/jog_dial_dimple.png
+++ b/core/res/res/drawable-xhdpi/jog_dial_dimple.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/jog_dial_dimple_dim.png b/core/res/res/drawable-xhdpi/jog_dial_dimple_dim.png
index 720ff80..15fcb14 100644
--- a/core/res/res/drawable-xhdpi/jog_dial_dimple_dim.png
+++ b/core/res/res/drawable-xhdpi/jog_dial_dimple_dim.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/keyboard_accessory_bg_landscape.9.png b/core/res/res/drawable-xhdpi/keyboard_accessory_bg_landscape.9.png
index e534908..9f73857 100644
--- a/core/res/res/drawable-xhdpi/keyboard_accessory_bg_landscape.9.png
+++ b/core/res/res/drawable-xhdpi/keyboard_accessory_bg_landscape.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/keyboard_background.9.png b/core/res/res/drawable-xhdpi/keyboard_background.9.png
index 33d8519..82adf0d 100644
--- a/core/res/res/drawable-xhdpi/keyboard_background.9.png
+++ b/core/res/res/drawable-xhdpi/keyboard_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/keyboard_key_feedback_background.9.png b/core/res/res/drawable-xhdpi/keyboard_key_feedback_background.9.png
index 6e8584b..cc7bd52 100644
--- a/core/res/res/drawable-xhdpi/keyboard_key_feedback_background.9.png
+++ b/core/res/res/drawable-xhdpi/keyboard_key_feedback_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/keyboard_key_feedback_more_background.9.png b/core/res/res/drawable-xhdpi/keyboard_key_feedback_more_background.9.png
index d983a95..12f5ce3 100644
--- a/core/res/res/drawable-xhdpi/keyboard_key_feedback_more_background.9.png
+++ b/core/res/res/drawable-xhdpi/keyboard_key_feedback_more_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/keyboard_popup_panel_background.9.png b/core/res/res/drawable-xhdpi/keyboard_popup_panel_background.9.png
index d9f4819..a21f75f 100644
--- a/core/res/res/drawable-xhdpi/keyboard_popup_panel_background.9.png
+++ b/core/res/res/drawable-xhdpi/keyboard_popup_panel_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/keyboard_popup_panel_trans_background.9.png b/core/res/res/drawable-xhdpi/keyboard_popup_panel_trans_background.9.png
index 9a19f78..f5643b3 100644
--- a/core/res/res/drawable-xhdpi/keyboard_popup_panel_trans_background.9.png
+++ b/core/res/res/drawable-xhdpi/keyboard_popup_panel_trans_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/light_header.9.png b/core/res/res/drawable-xhdpi/light_header.9.png
index 029dd2a..ccfcd01 100644
--- a/core/res/res/drawable-xhdpi/light_header.9.png
+++ b/core/res/res/drawable-xhdpi/light_header.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_activated_holo.9.png b/core/res/res/drawable-xhdpi/list_activated_holo.9.png
index eda10e6..488760b 100644
--- a/core/res/res/drawable-xhdpi/list_activated_holo.9.png
+++ b/core/res/res/drawable-xhdpi/list_activated_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_divider_holo_dark.9.png b/core/res/res/drawable-xhdpi/list_divider_holo_dark.9.png
index e62f011..af46699 100644
--- a/core/res/res/drawable-xhdpi/list_divider_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/list_divider_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_divider_holo_light.9.png b/core/res/res/drawable-xhdpi/list_divider_holo_light.9.png
index 65061c0..94d65b2 100644
--- a/core/res/res/drawable-xhdpi/list_divider_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/list_divider_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_divider_horizontal_holo_dark.9.png b/core/res/res/drawable-xhdpi/list_divider_horizontal_holo_dark.9.png
index 0c901de..ebb2ae8 100644
--- a/core/res/res/drawable-xhdpi/list_divider_horizontal_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/list_divider_horizontal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_focused_holo.9.png b/core/res/res/drawable-xhdpi/list_focused_holo.9.png
index b545f8e..e36eed7 100644
--- a/core/res/res/drawable-xhdpi/list_focused_holo.9.png
+++ b/core/res/res/drawable-xhdpi/list_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_longpressed_holo.9.png b/core/res/res/drawable-xhdpi/list_longpressed_holo.9.png
index eda10e6..488760b 100644
--- a/core/res/res/drawable-xhdpi/list_longpressed_holo.9.png
+++ b/core/res/res/drawable-xhdpi/list_longpressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_longpressed_holo_dark.9.png b/core/res/res/drawable-xhdpi/list_longpressed_holo_dark.9.png
index 1080244..a5eb97d 100644
--- a/core/res/res/drawable-xhdpi/list_longpressed_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/list_longpressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_longpressed_holo_light.9.png b/core/res/res/drawable-xhdpi/list_longpressed_holo_light.9.png
index 5532e88..434c1789 100644
--- a/core/res/res/drawable-xhdpi/list_longpressed_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/list_longpressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_pressed_holo_dark.9.png b/core/res/res/drawable-xhdpi/list_pressed_holo_dark.9.png
index 29037a0..32df932 100644
--- a/core/res/res/drawable-xhdpi/list_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/list_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_pressed_holo_light.9.png b/core/res/res/drawable-xhdpi/list_pressed_holo_light.9.png
index f4af926..2b78cf2 100644
--- a/core/res/res/drawable-xhdpi/list_pressed_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/list_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_section_divider_holo_dark.9.png b/core/res/res/drawable-xhdpi/list_section_divider_holo_dark.9.png
index 942d72e..e65a790 100644
--- a/core/res/res/drawable-xhdpi/list_section_divider_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/list_section_divider_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_section_divider_holo_light.9.png b/core/res/res/drawable-xhdpi/list_section_divider_holo_light.9.png
index 4ad088f..1318f38 100644
--- a/core/res/res/drawable-xhdpi/list_section_divider_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/list_section_divider_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_section_divider_mtrl_alpha.9.png b/core/res/res/drawable-xhdpi/list_section_divider_mtrl_alpha.9.png
index e053b39..4bf4435 100644
--- a/core/res/res/drawable-xhdpi/list_section_divider_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xhdpi/list_section_divider_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_section_header_holo_dark.9.png b/core/res/res/drawable-xhdpi/list_section_header_holo_dark.9.png
index 6cb42c1..6c921a3 100644
--- a/core/res/res/drawable-xhdpi/list_section_header_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/list_section_header_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_section_header_holo_light.9.png b/core/res/res/drawable-xhdpi/list_section_header_holo_light.9.png
index f646a41..da151e4 100644
--- a/core/res/res/drawable-xhdpi/list_section_header_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/list_section_header_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_selected_holo_dark.9.png b/core/res/res/drawable-xhdpi/list_selected_holo_dark.9.png
index e9e7c18..8364785 100644
--- a/core/res/res/drawable-xhdpi/list_selected_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/list_selected_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_selected_holo_light.9.png b/core/res/res/drawable-xhdpi/list_selected_holo_light.9.png
index 74e3843..8f1d8f6 100644
--- a/core/res/res/drawable-xhdpi/list_selected_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/list_selected_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_selector_activated_holo_dark.9.png b/core/res/res/drawable-xhdpi/list_selector_activated_holo_dark.9.png
index f176c7f..61fdbc4 100644
--- a/core/res/res/drawable-xhdpi/list_selector_activated_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/list_selector_activated_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_selector_activated_holo_light.9.png b/core/res/res/drawable-xhdpi/list_selector_activated_holo_light.9.png
index b13f340..370ee93 100644
--- a/core/res/res/drawable-xhdpi/list_selector_activated_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/list_selector_activated_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_selector_background_default.9.png b/core/res/res/drawable-xhdpi/list_selector_background_default.9.png
index 7261e96..615a45e 100644
--- a/core/res/res/drawable-xhdpi/list_selector_background_default.9.png
+++ b/core/res/res/drawable-xhdpi/list_selector_background_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_selector_background_default_light.9.png b/core/res/res/drawable-xhdpi/list_selector_background_default_light.9.png
index 1fc96e2..422a19e 100644
--- a/core/res/res/drawable-xhdpi/list_selector_background_default_light.9.png
+++ b/core/res/res/drawable-xhdpi/list_selector_background_default_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_selector_background_disabled.9.png b/core/res/res/drawable-xhdpi/list_selector_background_disabled.9.png
index f039081..077c52a 100644
--- a/core/res/res/drawable-xhdpi/list_selector_background_disabled.9.png
+++ b/core/res/res/drawable-xhdpi/list_selector_background_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_selector_background_disabled_light.9.png b/core/res/res/drawable-xhdpi/list_selector_background_disabled_light.9.png
index 9b22eff..5e64880 100644
--- a/core/res/res/drawable-xhdpi/list_selector_background_disabled_light.9.png
+++ b/core/res/res/drawable-xhdpi/list_selector_background_disabled_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_selector_background_focus.9.png b/core/res/res/drawable-xhdpi/list_selector_background_focus.9.png
index 79c4577..228bcd9 100644
--- a/core/res/res/drawable-xhdpi/list_selector_background_focus.9.png
+++ b/core/res/res/drawable-xhdpi/list_selector_background_focus.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_selector_background_focused.9.png b/core/res/res/drawable-xhdpi/list_selector_background_focused.9.png
index c8e7681..858f3d5 100644
--- a/core/res/res/drawable-xhdpi/list_selector_background_focused.9.png
+++ b/core/res/res/drawable-xhdpi/list_selector_background_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_selector_background_focused_light.9.png b/core/res/res/drawable-xhdpi/list_selector_background_focused_light.9.png
index c8e7681..858f3d5 100644
--- a/core/res/res/drawable-xhdpi/list_selector_background_focused_light.9.png
+++ b/core/res/res/drawable-xhdpi/list_selector_background_focused_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_selector_background_focused_selected.9.png b/core/res/res/drawable-xhdpi/list_selector_background_focused_selected.9.png
index f56a2dc..e899302 100644
--- a/core/res/res/drawable-xhdpi/list_selector_background_focused_selected.9.png
+++ b/core/res/res/drawable-xhdpi/list_selector_background_focused_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_selector_background_longpress.9.png b/core/res/res/drawable-xhdpi/list_selector_background_longpress.9.png
index 73fc783..336503f 100644
--- a/core/res/res/drawable-xhdpi/list_selector_background_longpress.9.png
+++ b/core/res/res/drawable-xhdpi/list_selector_background_longpress.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_selector_background_longpress_light.9.png b/core/res/res/drawable-xhdpi/list_selector_background_longpress_light.9.png
index ee50a53..d23e79a 100644
--- a/core/res/res/drawable-xhdpi/list_selector_background_longpress_light.9.png
+++ b/core/res/res/drawable-xhdpi/list_selector_background_longpress_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_selector_background_pressed.9.png b/core/res/res/drawable-xhdpi/list_selector_background_pressed.9.png
index 5b3ebe1..e9f6cef 100644
--- a/core/res/res/drawable-xhdpi/list_selector_background_pressed.9.png
+++ b/core/res/res/drawable-xhdpi/list_selector_background_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_selector_background_pressed_light.9.png b/core/res/res/drawable-xhdpi/list_selector_background_pressed_light.9.png
index a9a293c..f9ac9a6 100644
--- a/core/res/res/drawable-xhdpi/list_selector_background_pressed_light.9.png
+++ b/core/res/res/drawable-xhdpi/list_selector_background_pressed_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_selector_background_selected.9.png b/core/res/res/drawable-xhdpi/list_selector_background_selected.9.png
index 78358fe..436f462 100644
--- a/core/res/res/drawable-xhdpi/list_selector_background_selected.9.png
+++ b/core/res/res/drawable-xhdpi/list_selector_background_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_selector_background_selected_light.9.png b/core/res/res/drawable-xhdpi/list_selector_background_selected_light.9.png
index 7349da5..39b11ae 100644
--- a/core/res/res/drawable-xhdpi/list_selector_background_selected_light.9.png
+++ b/core/res/res/drawable-xhdpi/list_selector_background_selected_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_selector_disabled_holo_dark.9.png b/core/res/res/drawable-xhdpi/list_selector_disabled_holo_dark.9.png
index 88726b6..85905a8 100644
--- a/core/res/res/drawable-xhdpi/list_selector_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/list_selector_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_selector_disabled_holo_light.9.png b/core/res/res/drawable-xhdpi/list_selector_disabled_holo_light.9.png
index c6a7d4d..47ac0cf 100644
--- a/core/res/res/drawable-xhdpi/list_selector_disabled_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/list_selector_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_selector_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/list_selector_focused_holo_dark.9.png
index d9a26f4..fd58cf9 100644
--- a/core/res/res/drawable-xhdpi/list_selector_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/list_selector_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_selector_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/list_selector_focused_holo_light.9.png
index 7ea2b21..3c442b6 100644
--- a/core/res/res/drawable-xhdpi/list_selector_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/list_selector_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_selector_multiselect_holo_dark.9.png b/core/res/res/drawable-xhdpi/list_selector_multiselect_holo_dark.9.png
index 7033b0e..eecb6f8 100644
--- a/core/res/res/drawable-xhdpi/list_selector_multiselect_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/list_selector_multiselect_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_selector_multiselect_holo_light.9.png b/core/res/res/drawable-xhdpi/list_selector_multiselect_holo_light.9.png
index e638675..e08ea5a 100644
--- a/core/res/res/drawable-xhdpi/list_selector_multiselect_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/list_selector_multiselect_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_selector_pressed_holo_dark.9.png b/core/res/res/drawable-xhdpi/list_selector_pressed_holo_dark.9.png
index df19701..023ac10 100644
--- a/core/res/res/drawable-xhdpi/list_selector_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/list_selector_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_selector_pressed_holo_light.9.png b/core/res/res/drawable-xhdpi/list_selector_pressed_holo_light.9.png
index 6e5a6a9..52ba587 100644
--- a/core/res/res/drawable-xhdpi/list_selector_pressed_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/list_selector_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/magnified_region_frame.9.png b/core/res/res/drawable-xhdpi/magnified_region_frame.9.png
index 424b3d9..6c2fb46 100644
--- a/core/res/res/drawable-xhdpi/magnified_region_frame.9.png
+++ b/core/res/res/drawable-xhdpi/magnified_region_frame.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/maps_google_logo.png b/core/res/res/drawable-xhdpi/maps_google_logo.png
index 2cd6257..b04dd9e 100644
--- a/core/res/res/drawable-xhdpi/maps_google_logo.png
+++ b/core/res/res/drawable-xhdpi/maps_google_logo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/menu_background.9.png b/core/res/res/drawable-xhdpi/menu_background.9.png
index 3aa8ccb..67a2dc0 100644
--- a/core/res/res/drawable-xhdpi/menu_background.9.png
+++ b/core/res/res/drawable-xhdpi/menu_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/menu_background_fill_parent_width.9.png b/core/res/res/drawable-xhdpi/menu_background_fill_parent_width.9.png
index af08de2..9b08234 100644
--- a/core/res/res/drawable-xhdpi/menu_background_fill_parent_width.9.png
+++ b/core/res/res/drawable-xhdpi/menu_background_fill_parent_width.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_dark.9.png b/core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_dark.9.png
index abc48f8..3ef31fb 100644
--- a/core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_light.9.png b/core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_light.9.png
index 48905ed..909c976 100644
--- a/core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/menu_hardkey_panel_holo_dark.9.png b/core/res/res/drawable-xhdpi/menu_hardkey_panel_holo_dark.9.png
index c1ad023..dec0572 100644
--- a/core/res/res/drawable-xhdpi/menu_hardkey_panel_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/menu_hardkey_panel_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/menu_hardkey_panel_holo_light.9.png b/core/res/res/drawable-xhdpi/menu_hardkey_panel_holo_light.9.png
index a1e33d6..61adc99 100644
--- a/core/res/res/drawable-xhdpi/menu_hardkey_panel_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/menu_hardkey_panel_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/menu_popup_panel_holo_dark.9.png b/core/res/res/drawable-xhdpi/menu_popup_panel_holo_dark.9.png
index e85b0c2..5464846 100644
--- a/core/res/res/drawable-xhdpi/menu_popup_panel_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/menu_popup_panel_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/menu_popup_panel_holo_light.9.png b/core/res/res/drawable-xhdpi/menu_popup_panel_holo_light.9.png
index eea215d..75ab631 100644
--- a/core/res/res/drawable-xhdpi/menu_popup_panel_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/menu_popup_panel_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/menu_separator.9.png b/core/res/res/drawable-xhdpi/menu_separator.9.png
index 3c3722cb..c25ff7e 100644
--- a/core/res/res/drawable-xhdpi/menu_separator.9.png
+++ b/core/res/res/drawable-xhdpi/menu_separator.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/menu_submenu_background.9.png b/core/res/res/drawable-xhdpi/menu_submenu_background.9.png
index 4a8b2ad..9f2f35c 100644
--- a/core/res/res/drawable-xhdpi/menu_submenu_background.9.png
+++ b/core/res/res/drawable-xhdpi/menu_submenu_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/menuitem_background_focus.9.png b/core/res/res/drawable-xhdpi/menuitem_background_focus.9.png
index 83e4ae0..53a7012 100644
--- a/core/res/res/drawable-xhdpi/menuitem_background_focus.9.png
+++ b/core/res/res/drawable-xhdpi/menuitem_background_focus.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/menuitem_background_pressed.9.png b/core/res/res/drawable-xhdpi/menuitem_background_pressed.9.png
index 70a000f..a12370d 100644
--- a/core/res/res/drawable-xhdpi/menuitem_background_pressed.9.png
+++ b/core/res/res/drawable-xhdpi/menuitem_background_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/menuitem_background_solid_focused.9.png b/core/res/res/drawable-xhdpi/menuitem_background_solid_focused.9.png
index 671e756..533bda8 100644
--- a/core/res/res/drawable-xhdpi/menuitem_background_solid_focused.9.png
+++ b/core/res/res/drawable-xhdpi/menuitem_background_solid_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/menuitem_background_solid_pressed.9.png b/core/res/res/drawable-xhdpi/menuitem_background_solid_pressed.9.png
index 5f334d8..233e108 100644
--- a/core/res/res/drawable-xhdpi/menuitem_background_solid_pressed.9.png
+++ b/core/res/res/drawable-xhdpi/menuitem_background_solid_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/menuitem_checkbox_on.png b/core/res/res/drawable-xhdpi/menuitem_checkbox_on.png
index a7d2ad2..cafbebc 100644
--- a/core/res/res/drawable-xhdpi/menuitem_checkbox_on.png
+++ b/core/res/res/drawable-xhdpi/menuitem_checkbox_on.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/minitab_lt_focus.9.png b/core/res/res/drawable-xhdpi/minitab_lt_focus.9.png
index 7a0995b..803b44d 100644
--- a/core/res/res/drawable-xhdpi/minitab_lt_focus.9.png
+++ b/core/res/res/drawable-xhdpi/minitab_lt_focus.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/minitab_lt_press.9.png b/core/res/res/drawable-xhdpi/minitab_lt_press.9.png
index 7602d3e..8e0cfdb 100644
--- a/core/res/res/drawable-xhdpi/minitab_lt_press.9.png
+++ b/core/res/res/drawable-xhdpi/minitab_lt_press.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/minitab_lt_selected.9.png b/core/res/res/drawable-xhdpi/minitab_lt_selected.9.png
index 544fad5..974d521 100644
--- a/core/res/res/drawable-xhdpi/minitab_lt_selected.9.png
+++ b/core/res/res/drawable-xhdpi/minitab_lt_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/minitab_lt_unselected.9.png b/core/res/res/drawable-xhdpi/minitab_lt_unselected.9.png
index bcdb9d7..4e987cd 100644
--- a/core/res/res/drawable-xhdpi/minitab_lt_unselected.9.png
+++ b/core/res/res/drawable-xhdpi/minitab_lt_unselected.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/minitab_lt_unselected_press.9.png b/core/res/res/drawable-xhdpi/minitab_lt_unselected_press.9.png
index 8aabb89..65c62b7 100644
--- a/core/res/res/drawable-xhdpi/minitab_lt_unselected_press.9.png
+++ b/core/res/res/drawable-xhdpi/minitab_lt_unselected_press.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_disabled.9.png b/core/res/res/drawable-xhdpi/numberpicker_down_disabled.9.png
index ec92ea5..2c78c30 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_down_disabled.9.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_down_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_disabled_focused.9.png b/core/res/res/drawable-xhdpi/numberpicker_down_disabled_focused.9.png
index 03c020d..011bd5593 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_down_disabled_focused.9.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_down_disabled_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_normal.9.png b/core/res/res/drawable-xhdpi/numberpicker_down_normal.9.png
index 8637414..2dbb799 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_down_normal.9.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_down_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_pressed.9.png b/core/res/res/drawable-xhdpi/numberpicker_down_pressed.9.png
index bb56365..3422498 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_down_pressed.9.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_down_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_down_selected.9.png b/core/res/res/drawable-xhdpi/numberpicker_down_selected.9.png
index 4a076f6..2ae4a11 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_down_selected.9.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_down_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_input_disabled.9.png b/core/res/res/drawable-xhdpi/numberpicker_input_disabled.9.png
index d176022..43dbd52 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_input_disabled.9.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_input_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_input_normal.9.png b/core/res/res/drawable-xhdpi/numberpicker_input_normal.9.png
index dcacfcf..e29b0ef 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_input_normal.9.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_input_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_input_pressed.9.png b/core/res/res/drawable-xhdpi/numberpicker_input_pressed.9.png
index f8cb9e5..c4b6e85 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_input_pressed.9.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_input_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_input_selected.9.png b/core/res/res/drawable-xhdpi/numberpicker_input_selected.9.png
index 38c429f..514b7f3 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_input_selected.9.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_input_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_selection_divider.9.png b/core/res/res/drawable-xhdpi/numberpicker_selection_divider.9.png
index 97eb5fe..ce44e66 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_selection_divider.9.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_selection_divider.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_disabled.9.png b/core/res/res/drawable-xhdpi/numberpicker_up_disabled.9.png
index a1d8ae1..3a31f8c 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_up_disabled.9.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_up_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_disabled_focused.9.png b/core/res/res/drawable-xhdpi/numberpicker_up_disabled_focused.9.png
index 0256f32a..975c86f 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_up_disabled_focused.9.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_up_disabled_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_normal.9.png b/core/res/res/drawable-xhdpi/numberpicker_up_normal.9.png
index f6746a6..036b25e 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_up_normal.9.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_up_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_pressed.9.png b/core/res/res/drawable-xhdpi/numberpicker_up_pressed.9.png
index 1071c73..37cb783 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_up_pressed.9.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_up_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/numberpicker_up_selected.9.png b/core/res/res/drawable-xhdpi/numberpicker_up_selected.9.png
index f446d48..f38172f 100644
--- a/core/res/res/drawable-xhdpi/numberpicker_up_selected.9.png
+++ b/core/res/res/drawable-xhdpi/numberpicker_up_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/panel_background.9.png b/core/res/res/drawable-xhdpi/panel_background.9.png
index f3a3a9d..5bad2ec 100644
--- a/core/res/res/drawable-xhdpi/panel_background.9.png
+++ b/core/res/res/drawable-xhdpi/panel_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/panel_bg_holo_dark.9.png b/core/res/res/drawable-xhdpi/panel_bg_holo_dark.9.png
index aaf6d8b..8120722 100644
--- a/core/res/res/drawable-xhdpi/panel_bg_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/panel_bg_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/panel_bg_holo_light.9.png b/core/res/res/drawable-xhdpi/panel_bg_holo_light.9.png
index 6ea7615..d53ae70 100644
--- a/core/res/res/drawable-xhdpi/panel_bg_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/panel_bg_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/panel_picture_frame_bg_focus_blue.9.png b/core/res/res/drawable-xhdpi/panel_picture_frame_bg_focus_blue.9.png
index 8c7b0bd..4e81c8f 100644
--- a/core/res/res/drawable-xhdpi/panel_picture_frame_bg_focus_blue.9.png
+++ b/core/res/res/drawable-xhdpi/panel_picture_frame_bg_focus_blue.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/panel_picture_frame_bg_normal.9.png b/core/res/res/drawable-xhdpi/panel_picture_frame_bg_normal.9.png
index 5477a02..5b04c28 100644
--- a/core/res/res/drawable-xhdpi/panel_picture_frame_bg_normal.9.png
+++ b/core/res/res/drawable-xhdpi/panel_picture_frame_bg_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/panel_picture_frame_bg_pressed_blue.9.png b/core/res/res/drawable-xhdpi/panel_picture_frame_bg_pressed_blue.9.png
index d79a003..a150d97 100644
--- a/core/res/res/drawable-xhdpi/panel_picture_frame_bg_pressed_blue.9.png
+++ b/core/res/res/drawable-xhdpi/panel_picture_frame_bg_pressed_blue.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/password_field_default.9.png b/core/res/res/drawable-xhdpi/password_field_default.9.png
index 9aa6776..42ccf8f 100644
--- a/core/res/res/drawable-xhdpi/password_field_default.9.png
+++ b/core/res/res/drawable-xhdpi/password_field_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/password_keyboard_background_holo.9.png b/core/res/res/drawable-xhdpi/password_keyboard_background_holo.9.png
index 7f95130..62692f3 100644
--- a/core/res/res/drawable-xhdpi/password_keyboard_background_holo.9.png
+++ b/core/res/res/drawable-xhdpi/password_keyboard_background_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_accessibility_features.png b/core/res/res/drawable-xhdpi/perm_group_accessibility_features.png
index 53a12a1..b5de3cd 100644
--- a/core/res/res/drawable-xhdpi/perm_group_accessibility_features.png
+++ b/core/res/res/drawable-xhdpi/perm_group_accessibility_features.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_affects_battery.png b/core/res/res/drawable-xhdpi/perm_group_affects_battery.png
index 3527aa7..3a2cd0c 100644
--- a/core/res/res/drawable-xhdpi/perm_group_affects_battery.png
+++ b/core/res/res/drawable-xhdpi/perm_group_affects_battery.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_app_info.png b/core/res/res/drawable-xhdpi/perm_group_app_info.png
index 902b795..ac840b0 100644
--- a/core/res/res/drawable-xhdpi/perm_group_app_info.png
+++ b/core/res/res/drawable-xhdpi/perm_group_app_info.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_audio_settings.png b/core/res/res/drawable-xhdpi/perm_group_audio_settings.png
index 8100212..3e69c1e 100644
--- a/core/res/res/drawable-xhdpi/perm_group_audio_settings.png
+++ b/core/res/res/drawable-xhdpi/perm_group_audio_settings.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_bluetooth.png b/core/res/res/drawable-xhdpi/perm_group_bluetooth.png
index 754da87..0b3ce85 100644
--- a/core/res/res/drawable-xhdpi/perm_group_bluetooth.png
+++ b/core/res/res/drawable-xhdpi/perm_group_bluetooth.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_bookmarks.png b/core/res/res/drawable-xhdpi/perm_group_bookmarks.png
index 44525bc..b7fc61e 100644
--- a/core/res/res/drawable-xhdpi/perm_group_bookmarks.png
+++ b/core/res/res/drawable-xhdpi/perm_group_bookmarks.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_device_alarms.png b/core/res/res/drawable-xhdpi/perm_group_device_alarms.png
index 615578e..c84e0db 100644
--- a/core/res/res/drawable-xhdpi/perm_group_device_alarms.png
+++ b/core/res/res/drawable-xhdpi/perm_group_device_alarms.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_display.png b/core/res/res/drawable-xhdpi/perm_group_display.png
index 1489213..ec77c25 100644
--- a/core/res/res/drawable-xhdpi/perm_group_display.png
+++ b/core/res/res/drawable-xhdpi/perm_group_display.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_network.png b/core/res/res/drawable-xhdpi/perm_group_network.png
index ebe034f..8d1f6e7 100644
--- a/core/res/res/drawable-xhdpi/perm_group_network.png
+++ b/core/res/res/drawable-xhdpi/perm_group_network.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_personal_info.png b/core/res/res/drawable-xhdpi/perm_group_personal_info.png
index 5ae4111..124fc67 100644
--- a/core/res/res/drawable-xhdpi/perm_group_personal_info.png
+++ b/core/res/res/drawable-xhdpi/perm_group_personal_info.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_screenlock.png b/core/res/res/drawable-xhdpi/perm_group_screenlock.png
index 96d6873..9d443f0 100644
--- a/core/res/res/drawable-xhdpi/perm_group_screenlock.png
+++ b/core/res/res/drawable-xhdpi/perm_group_screenlock.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_shortrange_network.png b/core/res/res/drawable-xhdpi/perm_group_shortrange_network.png
index 2f0c2d9..7b6a6ee 100644
--- a/core/res/res/drawable-xhdpi/perm_group_shortrange_network.png
+++ b/core/res/res/drawable-xhdpi/perm_group_shortrange_network.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_status_bar.png b/core/res/res/drawable-xhdpi/perm_group_status_bar.png
index 8103320..2d55869 100644
--- a/core/res/res/drawable-xhdpi/perm_group_status_bar.png
+++ b/core/res/res/drawable-xhdpi/perm_group_status_bar.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_sync_settings.png b/core/res/res/drawable-xhdpi/perm_group_sync_settings.png
index 252a2a0..a63fe4f 100644
--- a/core/res/res/drawable-xhdpi/perm_group_sync_settings.png
+++ b/core/res/res/drawable-xhdpi/perm_group_sync_settings.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_system_clock.png b/core/res/res/drawable-xhdpi/perm_group_system_clock.png
index da8a915..77bd144 100644
--- a/core/res/res/drawable-xhdpi/perm_group_system_clock.png
+++ b/core/res/res/drawable-xhdpi/perm_group_system_clock.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_system_tools.png b/core/res/res/drawable-xhdpi/perm_group_system_tools.png
index 047c60c..a445c3b 100644
--- a/core/res/res/drawable-xhdpi/perm_group_system_tools.png
+++ b/core/res/res/drawable-xhdpi/perm_group_system_tools.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_voicemail.png b/core/res/res/drawable-xhdpi/perm_group_voicemail.png
index 430964d..3c8a4616 100644
--- a/core/res/res/drawable-xhdpi/perm_group_voicemail.png
+++ b/core/res/res/drawable-xhdpi/perm_group_voicemail.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_wallpaper.png b/core/res/res/drawable-xhdpi/perm_group_wallpaper.png
index 3b698d8..75d3c11 100644
--- a/core/res/res/drawable-xhdpi/perm_group_wallpaper.png
+++ b/core/res/res/drawable-xhdpi/perm_group_wallpaper.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/picture_emergency.png b/core/res/res/drawable-xhdpi/picture_emergency.png
index 08b421e..7852388 100644
--- a/core/res/res/drawable-xhdpi/picture_emergency.png
+++ b/core/res/res/drawable-xhdpi/picture_emergency.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/picture_frame.9.png b/core/res/res/drawable-xhdpi/picture_frame.9.png
index 69ef655..7681266 100644
--- a/core/res/res/drawable-xhdpi/picture_frame.9.png
+++ b/core/res/res/drawable-xhdpi/picture_frame.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_alias_large.png b/core/res/res/drawable-xhdpi/pointer_alias_large.png
index 813cd2a..ad595ed 100644
--- a/core/res/res/drawable-xhdpi/pointer_alias_large.png
+++ b/core/res/res/drawable-xhdpi/pointer_alias_large.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_all_scroll_large.png b/core/res/res/drawable-xhdpi/pointer_all_scroll_large.png
index f101077..6029f52 100644
--- a/core/res/res/drawable-xhdpi/pointer_all_scroll_large.png
+++ b/core/res/res/drawable-xhdpi/pointer_all_scroll_large.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_arrow.png b/core/res/res/drawable-xhdpi/pointer_arrow.png
index e2d9ed2..1cfd033 100644
--- a/core/res/res/drawable-xhdpi/pointer_arrow.png
+++ b/core/res/res/drawable-xhdpi/pointer_arrow.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_arrow_large.png b/core/res/res/drawable-xhdpi/pointer_arrow_large.png
index 0f9165b..dc9007a 100644
--- a/core/res/res/drawable-xhdpi/pointer_arrow_large.png
+++ b/core/res/res/drawable-xhdpi/pointer_arrow_large.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_cell_large.png b/core/res/res/drawable-xhdpi/pointer_cell_large.png
index b41f855..50119b7 100644
--- a/core/res/res/drawable-xhdpi/pointer_cell_large.png
+++ b/core/res/res/drawable-xhdpi/pointer_cell_large.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_context_menu_large.png b/core/res/res/drawable-xhdpi/pointer_context_menu_large.png
index 6264e0b..148cf87 100644
--- a/core/res/res/drawable-xhdpi/pointer_context_menu_large.png
+++ b/core/res/res/drawable-xhdpi/pointer_context_menu_large.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_copy.png b/core/res/res/drawable-xhdpi/pointer_copy.png
index f28a3e9..0cdbf21 100644
--- a/core/res/res/drawable-xhdpi/pointer_copy.png
+++ b/core/res/res/drawable-xhdpi/pointer_copy.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_copy_large.png b/core/res/res/drawable-xhdpi/pointer_copy_large.png
index 5e7f375..0e1350c 100644
--- a/core/res/res/drawable-xhdpi/pointer_copy_large.png
+++ b/core/res/res/drawable-xhdpi/pointer_copy_large.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_crosshair_large.png b/core/res/res/drawable-xhdpi/pointer_crosshair_large.png
index d5f4502..fc59291 100644
--- a/core/res/res/drawable-xhdpi/pointer_crosshair_large.png
+++ b/core/res/res/drawable-xhdpi/pointer_crosshair_large.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_grab_large.png b/core/res/res/drawable-xhdpi/pointer_grab_large.png
index bf99b79..df98d89 100644
--- a/core/res/res/drawable-xhdpi/pointer_grab_large.png
+++ b/core/res/res/drawable-xhdpi/pointer_grab_large.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_grabbing_large.png b/core/res/res/drawable-xhdpi/pointer_grabbing_large.png
index e576bcd..f2d043c 100644
--- a/core/res/res/drawable-xhdpi/pointer_grabbing_large.png
+++ b/core/res/res/drawable-xhdpi/pointer_grabbing_large.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_hand_large.png b/core/res/res/drawable-xhdpi/pointer_hand_large.png
index 76fa09b..3113589 100644
--- a/core/res/res/drawable-xhdpi/pointer_hand_large.png
+++ b/core/res/res/drawable-xhdpi/pointer_hand_large.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_help.png b/core/res/res/drawable-xhdpi/pointer_help.png
index 98a6632..abcf923 100644
--- a/core/res/res/drawable-xhdpi/pointer_help.png
+++ b/core/res/res/drawable-xhdpi/pointer_help.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_help_large.png b/core/res/res/drawable-xhdpi/pointer_help_large.png
index a45f039..b745e1e 100644
--- a/core/res/res/drawable-xhdpi/pointer_help_large.png
+++ b/core/res/res/drawable-xhdpi/pointer_help_large.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_horizontal_double_arrow_large.png b/core/res/res/drawable-xhdpi/pointer_horizontal_double_arrow_large.png
index 9b2a312..9c8fa5c 100644
--- a/core/res/res/drawable-xhdpi/pointer_horizontal_double_arrow_large.png
+++ b/core/res/res/drawable-xhdpi/pointer_horizontal_double_arrow_large.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_nodrop.png b/core/res/res/drawable-xhdpi/pointer_nodrop.png
index c56bfbb..8e93f33 100644
--- a/core/res/res/drawable-xhdpi/pointer_nodrop.png
+++ b/core/res/res/drawable-xhdpi/pointer_nodrop.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_nodrop_large.png b/core/res/res/drawable-xhdpi/pointer_nodrop_large.png
index f140532..a392da7 100644
--- a/core/res/res/drawable-xhdpi/pointer_nodrop_large.png
+++ b/core/res/res/drawable-xhdpi/pointer_nodrop_large.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_spot_anchor.png b/core/res/res/drawable-xhdpi/pointer_spot_anchor.png
index fa9226e..a1dcc14 100644
--- a/core/res/res/drawable-xhdpi/pointer_spot_anchor.png
+++ b/core/res/res/drawable-xhdpi/pointer_spot_anchor.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_spot_hover.png b/core/res/res/drawable-xhdpi/pointer_spot_hover.png
index f09a778..668f841 100644
--- a/core/res/res/drawable-xhdpi/pointer_spot_hover.png
+++ b/core/res/res/drawable-xhdpi/pointer_spot_hover.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_spot_touch.png b/core/res/res/drawable-xhdpi/pointer_spot_touch.png
index 53d7a20..2e922db 100644
--- a/core/res/res/drawable-xhdpi/pointer_spot_touch.png
+++ b/core/res/res/drawable-xhdpi/pointer_spot_touch.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_text_large.png b/core/res/res/drawable-xhdpi/pointer_text_large.png
index 56be154..d9ce209 100644
--- a/core/res/res/drawable-xhdpi/pointer_text_large.png
+++ b/core/res/res/drawable-xhdpi/pointer_text_large.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_top_left_diagonal_double_arrow_large.png b/core/res/res/drawable-xhdpi/pointer_top_left_diagonal_double_arrow_large.png
index 9e6a8b6..fcfa405 100644
--- a/core/res/res/drawable-xhdpi/pointer_top_left_diagonal_double_arrow_large.png
+++ b/core/res/res/drawable-xhdpi/pointer_top_left_diagonal_double_arrow_large.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_top_right_diagonal_double_arrow_large.png b/core/res/res/drawable-xhdpi/pointer_top_right_diagonal_double_arrow_large.png
index 2631094c8..39c5f1a 100644
--- a/core/res/res/drawable-xhdpi/pointer_top_right_diagonal_double_arrow_large.png
+++ b/core/res/res/drawable-xhdpi/pointer_top_right_diagonal_double_arrow_large.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_vertical_double_arrow_large.png b/core/res/res/drawable-xhdpi/pointer_vertical_double_arrow_large.png
index 5ec65e01..191f103 100644
--- a/core/res/res/drawable-xhdpi/pointer_vertical_double_arrow_large.png
+++ b/core/res/res/drawable-xhdpi/pointer_vertical_double_arrow_large.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_vertical_text_large.png b/core/res/res/drawable-xhdpi/pointer_vertical_text_large.png
index 26c46de..d3f729a 100644
--- a/core/res/res/drawable-xhdpi/pointer_vertical_text_large.png
+++ b/core/res/res/drawable-xhdpi/pointer_vertical_text_large.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_0.png b/core/res/res/drawable-xhdpi/pointer_wait_0.png
index 5396784..013aaf6 100644
--- a/core/res/res/drawable-xhdpi/pointer_wait_0.png
+++ b/core/res/res/drawable-xhdpi/pointer_wait_0.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_1.png b/core/res/res/drawable-xhdpi/pointer_wait_1.png
index 25edbf5..7fb0300 100644
--- a/core/res/res/drawable-xhdpi/pointer_wait_1.png
+++ b/core/res/res/drawable-xhdpi/pointer_wait_1.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_10.png b/core/res/res/drawable-xhdpi/pointer_wait_10.png
index 96d93a90..90efa0a 100644
--- a/core/res/res/drawable-xhdpi/pointer_wait_10.png
+++ b/core/res/res/drawable-xhdpi/pointer_wait_10.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_11.png b/core/res/res/drawable-xhdpi/pointer_wait_11.png
index cd78675..7c303a2 100644
--- a/core/res/res/drawable-xhdpi/pointer_wait_11.png
+++ b/core/res/res/drawable-xhdpi/pointer_wait_11.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_12.png b/core/res/res/drawable-xhdpi/pointer_wait_12.png
index 1b2c7b2..20a1fa8 100644
--- a/core/res/res/drawable-xhdpi/pointer_wait_12.png
+++ b/core/res/res/drawable-xhdpi/pointer_wait_12.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_13.png b/core/res/res/drawable-xhdpi/pointer_wait_13.png
index 3b00f10..4585a39 100644
--- a/core/res/res/drawable-xhdpi/pointer_wait_13.png
+++ b/core/res/res/drawable-xhdpi/pointer_wait_13.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_14.png b/core/res/res/drawable-xhdpi/pointer_wait_14.png
index eca5c3f..bdf0e5c 100644
--- a/core/res/res/drawable-xhdpi/pointer_wait_14.png
+++ b/core/res/res/drawable-xhdpi/pointer_wait_14.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_15.png b/core/res/res/drawable-xhdpi/pointer_wait_15.png
index 0fc2085..e39c28c 100644
--- a/core/res/res/drawable-xhdpi/pointer_wait_15.png
+++ b/core/res/res/drawable-xhdpi/pointer_wait_15.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_16.png b/core/res/res/drawable-xhdpi/pointer_wait_16.png
index db13cf6..7288141 100644
--- a/core/res/res/drawable-xhdpi/pointer_wait_16.png
+++ b/core/res/res/drawable-xhdpi/pointer_wait_16.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_17.png b/core/res/res/drawable-xhdpi/pointer_wait_17.png
index 9b6fac5..b35da18 100644
--- a/core/res/res/drawable-xhdpi/pointer_wait_17.png
+++ b/core/res/res/drawable-xhdpi/pointer_wait_17.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_18.png b/core/res/res/drawable-xhdpi/pointer_wait_18.png
index c56ff6c..0a61dd6 100644
--- a/core/res/res/drawable-xhdpi/pointer_wait_18.png
+++ b/core/res/res/drawable-xhdpi/pointer_wait_18.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_19.png b/core/res/res/drawable-xhdpi/pointer_wait_19.png
index 22b7c90..1920c77 100644
--- a/core/res/res/drawable-xhdpi/pointer_wait_19.png
+++ b/core/res/res/drawable-xhdpi/pointer_wait_19.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_2.png b/core/res/res/drawable-xhdpi/pointer_wait_2.png
index 4bdbe3f..c6b3861 100644
--- a/core/res/res/drawable-xhdpi/pointer_wait_2.png
+++ b/core/res/res/drawable-xhdpi/pointer_wait_2.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_20.png b/core/res/res/drawable-xhdpi/pointer_wait_20.png
index 6d042fb..b27358b 100644
--- a/core/res/res/drawable-xhdpi/pointer_wait_20.png
+++ b/core/res/res/drawable-xhdpi/pointer_wait_20.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_21.png b/core/res/res/drawable-xhdpi/pointer_wait_21.png
index e3ab63f..c1f9076 100644
--- a/core/res/res/drawable-xhdpi/pointer_wait_21.png
+++ b/core/res/res/drawable-xhdpi/pointer_wait_21.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_22.png b/core/res/res/drawable-xhdpi/pointer_wait_22.png
index b25f6b7d..6cc0c13 100644
--- a/core/res/res/drawable-xhdpi/pointer_wait_22.png
+++ b/core/res/res/drawable-xhdpi/pointer_wait_22.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_23.png b/core/res/res/drawable-xhdpi/pointer_wait_23.png
index 49faba9..7df525c 100644
--- a/core/res/res/drawable-xhdpi/pointer_wait_23.png
+++ b/core/res/res/drawable-xhdpi/pointer_wait_23.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_24.png b/core/res/res/drawable-xhdpi/pointer_wait_24.png
index e91c340..008e273 100644
--- a/core/res/res/drawable-xhdpi/pointer_wait_24.png
+++ b/core/res/res/drawable-xhdpi/pointer_wait_24.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_25.png b/core/res/res/drawable-xhdpi/pointer_wait_25.png
index f4785c6..59f02d9 100644
--- a/core/res/res/drawable-xhdpi/pointer_wait_25.png
+++ b/core/res/res/drawable-xhdpi/pointer_wait_25.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_26.png b/core/res/res/drawable-xhdpi/pointer_wait_26.png
index ea902f8..852b0bf 100644
--- a/core/res/res/drawable-xhdpi/pointer_wait_26.png
+++ b/core/res/res/drawable-xhdpi/pointer_wait_26.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_27.png b/core/res/res/drawable-xhdpi/pointer_wait_27.png
index 7d628c3..aba6292 100644
--- a/core/res/res/drawable-xhdpi/pointer_wait_27.png
+++ b/core/res/res/drawable-xhdpi/pointer_wait_27.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_28.png b/core/res/res/drawable-xhdpi/pointer_wait_28.png
index 92d6dc1..e59af43 100644
--- a/core/res/res/drawable-xhdpi/pointer_wait_28.png
+++ b/core/res/res/drawable-xhdpi/pointer_wait_28.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_29.png b/core/res/res/drawable-xhdpi/pointer_wait_29.png
index 5a8d18915..a195c29 100644
--- a/core/res/res/drawable-xhdpi/pointer_wait_29.png
+++ b/core/res/res/drawable-xhdpi/pointer_wait_29.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_3.png b/core/res/res/drawable-xhdpi/pointer_wait_3.png
index de4d79c..fb40e6f 100644
--- a/core/res/res/drawable-xhdpi/pointer_wait_3.png
+++ b/core/res/res/drawable-xhdpi/pointer_wait_3.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_30.png b/core/res/res/drawable-xhdpi/pointer_wait_30.png
index ba04b5e..0d19d28 100644
--- a/core/res/res/drawable-xhdpi/pointer_wait_30.png
+++ b/core/res/res/drawable-xhdpi/pointer_wait_30.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_31.png b/core/res/res/drawable-xhdpi/pointer_wait_31.png
index 3ef8e98..49066b6 100644
--- a/core/res/res/drawable-xhdpi/pointer_wait_31.png
+++ b/core/res/res/drawable-xhdpi/pointer_wait_31.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_32.png b/core/res/res/drawable-xhdpi/pointer_wait_32.png
index 3297a7d..43f7543 100644
--- a/core/res/res/drawable-xhdpi/pointer_wait_32.png
+++ b/core/res/res/drawable-xhdpi/pointer_wait_32.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_33.png b/core/res/res/drawable-xhdpi/pointer_wait_33.png
index b0ac3b9..3664ea8 100644
--- a/core/res/res/drawable-xhdpi/pointer_wait_33.png
+++ b/core/res/res/drawable-xhdpi/pointer_wait_33.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_34.png b/core/res/res/drawable-xhdpi/pointer_wait_34.png
index 0eaa386..e4c3919 100644
--- a/core/res/res/drawable-xhdpi/pointer_wait_34.png
+++ b/core/res/res/drawable-xhdpi/pointer_wait_34.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_35.png b/core/res/res/drawable-xhdpi/pointer_wait_35.png
index 73894d8..e58777a 100644
--- a/core/res/res/drawable-xhdpi/pointer_wait_35.png
+++ b/core/res/res/drawable-xhdpi/pointer_wait_35.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_4.png b/core/res/res/drawable-xhdpi/pointer_wait_4.png
index ea44e85..552b735 100644
--- a/core/res/res/drawable-xhdpi/pointer_wait_4.png
+++ b/core/res/res/drawable-xhdpi/pointer_wait_4.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_5.png b/core/res/res/drawable-xhdpi/pointer_wait_5.png
index 46c399d..cd2bfa1 100644
--- a/core/res/res/drawable-xhdpi/pointer_wait_5.png
+++ b/core/res/res/drawable-xhdpi/pointer_wait_5.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_6.png b/core/res/res/drawable-xhdpi/pointer_wait_6.png
index 3b9aff6..f7c71b9 100644
--- a/core/res/res/drawable-xhdpi/pointer_wait_6.png
+++ b/core/res/res/drawable-xhdpi/pointer_wait_6.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_7.png b/core/res/res/drawable-xhdpi/pointer_wait_7.png
index a54edc0..3fa202e 100644
--- a/core/res/res/drawable-xhdpi/pointer_wait_7.png
+++ b/core/res/res/drawable-xhdpi/pointer_wait_7.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_8.png b/core/res/res/drawable-xhdpi/pointer_wait_8.png
index 2f30732..e0e50ae 100644
--- a/core/res/res/drawable-xhdpi/pointer_wait_8.png
+++ b/core/res/res/drawable-xhdpi/pointer_wait_8.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_wait_9.png b/core/res/res/drawable-xhdpi/pointer_wait_9.png
index f39c7a7..e3de26f 100644
--- a/core/res/res/drawable-xhdpi/pointer_wait_9.png
+++ b/core/res/res/drawable-xhdpi/pointer_wait_9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_zoom_in_large.png b/core/res/res/drawable-xhdpi/pointer_zoom_in_large.png
index c2b845f..beabbd2 100644
--- a/core/res/res/drawable-xhdpi/pointer_zoom_in_large.png
+++ b/core/res/res/drawable-xhdpi/pointer_zoom_in_large.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_zoom_out_large.png b/core/res/res/drawable-xhdpi/pointer_zoom_out_large.png
index 148ed25..b748f07 100644
--- a/core/res/res/drawable-xhdpi/pointer_zoom_out_large.png
+++ b/core/res/res/drawable-xhdpi/pointer_zoom_out_large.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_background_mtrl_mult.9.png b/core/res/res/drawable-xhdpi/popup_background_mtrl_mult.9.png
index a081ceb..0630de3 100644
--- a/core/res/res/drawable-xhdpi/popup_background_mtrl_mult.9.png
+++ b/core/res/res/drawable-xhdpi/popup_background_mtrl_mult.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_bottom_bright.9.png b/core/res/res/drawable-xhdpi/popup_bottom_bright.9.png
index cdc0afb..22e83fd 100644
--- a/core/res/res/drawable-xhdpi/popup_bottom_bright.9.png
+++ b/core/res/res/drawable-xhdpi/popup_bottom_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_bottom_dark.9.png b/core/res/res/drawable-xhdpi/popup_bottom_dark.9.png
index 36b0448..4939a04 100644
--- a/core/res/res/drawable-xhdpi/popup_bottom_dark.9.png
+++ b/core/res/res/drawable-xhdpi/popup_bottom_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_bottom_medium.9.png b/core/res/res/drawable-xhdpi/popup_bottom_medium.9.png
index 3a7a8b3..5a6be90 100644
--- a/core/res/res/drawable-xhdpi/popup_bottom_medium.9.png
+++ b/core/res/res/drawable-xhdpi/popup_bottom_medium.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_center_bright.9.png b/core/res/res/drawable-xhdpi/popup_center_bright.9.png
index 97614e3..26e1477 100644
--- a/core/res/res/drawable-xhdpi/popup_center_bright.9.png
+++ b/core/res/res/drawable-xhdpi/popup_center_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_center_dark.9.png b/core/res/res/drawable-xhdpi/popup_center_dark.9.png
index 87378e1..b255d71 100644
--- a/core/res/res/drawable-xhdpi/popup_center_dark.9.png
+++ b/core/res/res/drawable-xhdpi/popup_center_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_center_medium.9.png b/core/res/res/drawable-xhdpi/popup_center_medium.9.png
index ea29ed4..de33170 100644
--- a/core/res/res/drawable-xhdpi/popup_center_medium.9.png
+++ b/core/res/res/drawable-xhdpi/popup_center_medium.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_full_bright.9.png b/core/res/res/drawable-xhdpi/popup_full_bright.9.png
index f10dd85..0bcef38 100644
--- a/core/res/res/drawable-xhdpi/popup_full_bright.9.png
+++ b/core/res/res/drawable-xhdpi/popup_full_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_full_dark.9.png b/core/res/res/drawable-xhdpi/popup_full_dark.9.png
index 7de3e9d..a5326c5 100644
--- a/core/res/res/drawable-xhdpi/popup_full_dark.9.png
+++ b/core/res/res/drawable-xhdpi/popup_full_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_inline_error_above_am.9.png b/core/res/res/drawable-xhdpi/popup_inline_error_above_am.9.png
index e382712..fb39954 100644
--- a/core/res/res/drawable-xhdpi/popup_inline_error_above_am.9.png
+++ b/core/res/res/drawable-xhdpi/popup_inline_error_above_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_inline_error_above_holo_dark_am.9.png b/core/res/res/drawable-xhdpi/popup_inline_error_above_holo_dark_am.9.png
index a210f3c..542856b 100644
--- a/core/res/res/drawable-xhdpi/popup_inline_error_above_holo_dark_am.9.png
+++ b/core/res/res/drawable-xhdpi/popup_inline_error_above_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_inline_error_above_holo_light_am.9.png b/core/res/res/drawable-xhdpi/popup_inline_error_above_holo_light_am.9.png
index d69b772..aba257b 100644
--- a/core/res/res/drawable-xhdpi/popup_inline_error_above_holo_light_am.9.png
+++ b/core/res/res/drawable-xhdpi/popup_inline_error_above_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_inline_error_am.9.png b/core/res/res/drawable-xhdpi/popup_inline_error_am.9.png
index a24e607..de35ed0 100644
--- a/core/res/res/drawable-xhdpi/popup_inline_error_am.9.png
+++ b/core/res/res/drawable-xhdpi/popup_inline_error_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_inline_error_holo_dark_am.9.png b/core/res/res/drawable-xhdpi/popup_inline_error_holo_dark_am.9.png
index f106329..c83aefa 100644
--- a/core/res/res/drawable-xhdpi/popup_inline_error_holo_dark_am.9.png
+++ b/core/res/res/drawable-xhdpi/popup_inline_error_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_inline_error_holo_light_am.9.png b/core/res/res/drawable-xhdpi/popup_inline_error_holo_light_am.9.png
index 0c65386..31b7db5 100644
--- a/core/res/res/drawable-xhdpi/popup_inline_error_holo_light_am.9.png
+++ b/core/res/res/drawable-xhdpi/popup_inline_error_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_top_bright.9.png b/core/res/res/drawable-xhdpi/popup_top_bright.9.png
index 64e4139..02217cd 100644
--- a/core/res/res/drawable-xhdpi/popup_top_bright.9.png
+++ b/core/res/res/drawable-xhdpi/popup_top_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_top_dark.9.png b/core/res/res/drawable-xhdpi/popup_top_dark.9.png
index 902bc29..6f910b8 100644
--- a/core/res/res/drawable-xhdpi/popup_top_dark.9.png
+++ b/core/res/res/drawable-xhdpi/popup_top_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/presence_audio_away.png b/core/res/res/drawable-xhdpi/presence_audio_away.png
index 4fc6f6a..c709a5c 100644
--- a/core/res/res/drawable-xhdpi/presence_audio_away.png
+++ b/core/res/res/drawable-xhdpi/presence_audio_away.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/presence_audio_busy.png b/core/res/res/drawable-xhdpi/presence_audio_busy.png
index ca45ac9..f188ab3 100644
--- a/core/res/res/drawable-xhdpi/presence_audio_busy.png
+++ b/core/res/res/drawable-xhdpi/presence_audio_busy.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/presence_audio_online.png b/core/res/res/drawable-xhdpi/presence_audio_online.png
index 595c730..8dbb10e 100644
--- a/core/res/res/drawable-xhdpi/presence_audio_online.png
+++ b/core/res/res/drawable-xhdpi/presence_audio_online.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/presence_away.png b/core/res/res/drawable-xhdpi/presence_away.png
index 1478e72..e8a9e8ec 100644
--- a/core/res/res/drawable-xhdpi/presence_away.png
+++ b/core/res/res/drawable-xhdpi/presence_away.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/presence_busy.png b/core/res/res/drawable-xhdpi/presence_busy.png
index 8278ce2..f5b79b2 100644
--- a/core/res/res/drawable-xhdpi/presence_busy.png
+++ b/core/res/res/drawable-xhdpi/presence_busy.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/presence_invisible.png b/core/res/res/drawable-xhdpi/presence_invisible.png
index 9bb6cef..a2eb2af 100644
--- a/core/res/res/drawable-xhdpi/presence_invisible.png
+++ b/core/res/res/drawable-xhdpi/presence_invisible.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/presence_offline.png b/core/res/res/drawable-xhdpi/presence_offline.png
index fc7ba24..deb29a8 100644
--- a/core/res/res/drawable-xhdpi/presence_offline.png
+++ b/core/res/res/drawable-xhdpi/presence_offline.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/presence_online.png b/core/res/res/drawable-xhdpi/presence_online.png
index e2aef11..335ab60 100644
--- a/core/res/res/drawable-xhdpi/presence_online.png
+++ b/core/res/res/drawable-xhdpi/presence_online.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/presence_video_away.png b/core/res/res/drawable-xhdpi/presence_video_away.png
index 02f7d63..da4273a 100644
--- a/core/res/res/drawable-xhdpi/presence_video_away.png
+++ b/core/res/res/drawable-xhdpi/presence_video_away.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/presence_video_busy.png b/core/res/res/drawable-xhdpi/presence_video_busy.png
index db0bec7..d9eacd5 100644
--- a/core/res/res/drawable-xhdpi/presence_video_busy.png
+++ b/core/res/res/drawable-xhdpi/presence_video_busy.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/presence_video_online.png b/core/res/res/drawable-xhdpi/presence_video_online.png
index e12be95..37f3b46 100644
--- a/core/res/res/drawable-xhdpi/presence_video_online.png
+++ b/core/res/res/drawable-xhdpi/presence_video_online.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pressed_application_background_static.png b/core/res/res/drawable-xhdpi/pressed_application_background_static.png
index b70de9e..934bf86 100644
--- a/core/res/res/drawable-xhdpi/pressed_application_background_static.png
+++ b/core/res/res/drawable-xhdpi/pressed_application_background_static.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/progress_bg_holo_dark.9.png b/core/res/res/drawable-xhdpi/progress_bg_holo_dark.9.png
index 3499528..3c8d388 100644
--- a/core/res/res/drawable-xhdpi/progress_bg_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/progress_bg_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/progress_bg_holo_light.9.png b/core/res/res/drawable-xhdpi/progress_bg_holo_light.9.png
index cbd19ac..9206d61 100644
--- a/core/res/res/drawable-xhdpi/progress_bg_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/progress_bg_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/progress_primary_holo_dark.9.png b/core/res/res/drawable-xhdpi/progress_primary_holo_dark.9.png
index f1069fd..ab8ceaf 100644
--- a/core/res/res/drawable-xhdpi/progress_primary_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/progress_primary_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/progress_primary_holo_light.9.png b/core/res/res/drawable-xhdpi/progress_primary_holo_light.9.png
index e62123c..f31435a 100644
--- a/core/res/res/drawable-xhdpi/progress_primary_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/progress_primary_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/progress_secondary_holo_dark.9.png b/core/res/res/drawable-xhdpi/progress_secondary_holo_dark.9.png
index 06ae19c..d34fcb7 100644
--- a/core/res/res/drawable-xhdpi/progress_secondary_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/progress_secondary_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/progress_secondary_holo_light.9.png b/core/res/res/drawable-xhdpi/progress_secondary_holo_light.9.png
index 37c6d5f..0083d20 100644
--- a/core/res/res/drawable-xhdpi/progress_secondary_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/progress_secondary_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/progressbar_indeterminate1.png b/core/res/res/drawable-xhdpi/progressbar_indeterminate1.png
index 7f01aa4..e98d4c0 100644
--- a/core/res/res/drawable-xhdpi/progressbar_indeterminate1.png
+++ b/core/res/res/drawable-xhdpi/progressbar_indeterminate1.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/progressbar_indeterminate2.png b/core/res/res/drawable-xhdpi/progressbar_indeterminate2.png
index 3105385..1c4d116 100644
--- a/core/res/res/drawable-xhdpi/progressbar_indeterminate2.png
+++ b/core/res/res/drawable-xhdpi/progressbar_indeterminate2.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/progressbar_indeterminate3.png b/core/res/res/drawable-xhdpi/progressbar_indeterminate3.png
index 248b49a..cf16a31 100644
--- a/core/res/res/drawable-xhdpi/progressbar_indeterminate3.png
+++ b/core/res/res/drawable-xhdpi/progressbar_indeterminate3.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo1.png b/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo1.png
index ae847c9..ede3d84 100644
--- a/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo1.png
+++ b/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo1.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo2.png b/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo2.png
index 7bf3ad6..c1323bf 100644
--- a/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo2.png
+++ b/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo2.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo3.png b/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo3.png
index 6c6341b..fb2ccfc 100644
--- a/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo3.png
+++ b/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo3.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo4.png b/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo4.png
index d7bb796..de3cd71 100644
--- a/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo4.png
+++ b/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo4.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo5.png b/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo5.png
index 255fcb8..b55372f 100644
--- a/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo5.png
+++ b/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo5.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo6.png b/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo6.png
index 6e5207e..b10c3dc 100644
--- a/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo6.png
+++ b/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo6.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo7.png b/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo7.png
index 7223bc0..55a82e7 100644
--- a/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo7.png
+++ b/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo7.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo8.png b/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo8.png
index ebcbe51..70e5208 100644
--- a/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo8.png
+++ b/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo8.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/quickactions_arrowdown_left_holo_dark.9.png b/core/res/res/drawable-xhdpi/quickactions_arrowdown_left_holo_dark.9.png
index 3f23144..9b249e7 100644
--- a/core/res/res/drawable-xhdpi/quickactions_arrowdown_left_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/quickactions_arrowdown_left_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/quickactions_arrowdown_left_holo_light.9.png b/core/res/res/drawable-xhdpi/quickactions_arrowdown_left_holo_light.9.png
index 41848dd..48d281c 100644
--- a/core/res/res/drawable-xhdpi/quickactions_arrowdown_left_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/quickactions_arrowdown_left_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/quickactions_arrowdown_right_holo_dark.9.png b/core/res/res/drawable-xhdpi/quickactions_arrowdown_right_holo_dark.9.png
index b2a1d8c..12764bd 100644
--- a/core/res/res/drawable-xhdpi/quickactions_arrowdown_right_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/quickactions_arrowdown_right_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/quickactions_arrowdown_right_holo_light.9.png b/core/res/res/drawable-xhdpi/quickactions_arrowdown_right_holo_light.9.png
index 27218f2..32747d4 100644
--- a/core/res/res/drawable-xhdpi/quickactions_arrowdown_right_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/quickactions_arrowdown_right_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/quickactions_arrowup_left_holo_dark.9.png b/core/res/res/drawable-xhdpi/quickactions_arrowup_left_holo_dark.9.png
index 49d1ed5..2c2e160 100644
--- a/core/res/res/drawable-xhdpi/quickactions_arrowup_left_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/quickactions_arrowup_left_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/quickactions_arrowup_left_holo_light.9.png b/core/res/res/drawable-xhdpi/quickactions_arrowup_left_holo_light.9.png
index 8be8ac8..adb183e 100644
--- a/core/res/res/drawable-xhdpi/quickactions_arrowup_left_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/quickactions_arrowup_left_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/quickactions_arrowup_left_right_holo_dark.9.png b/core/res/res/drawable-xhdpi/quickactions_arrowup_left_right_holo_dark.9.png
index 3f9e4aa..0b19088 100644
--- a/core/res/res/drawable-xhdpi/quickactions_arrowup_left_right_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/quickactions_arrowup_left_right_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/quickactions_arrowup_right_holo_light.9.png b/core/res/res/drawable-xhdpi/quickactions_arrowup_right_holo_light.9.png
index 46f3640..5162af8 100644
--- a/core/res/res/drawable-xhdpi/quickactions_arrowup_right_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/quickactions_arrowup_right_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_focused_dark_am.9.png b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_focused_dark_am.9.png
index 6927834..a645a5d 100644
--- a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_focused_dark_am.9.png
+++ b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_focused_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_focused_light_am.9.png b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_focused_light_am.9.png
index 4bce527..38a400f 100644
--- a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_focused_light_am.9.png
+++ b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_focused_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_normal_dark_am.9.png b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_normal_dark_am.9.png
index 99dbfcc..42f28a6 100644
--- a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_normal_dark_am.9.png
+++ b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_normal_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_normal_light_am.9.png b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_normal_light_am.9.png
index 2d3e5c8..88951cb 100644
--- a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_normal_light_am.9.png
+++ b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_normal_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_pressed_dark_am.9.png b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_pressed_dark_am.9.png
index 16c1e00..72ecca6 100644
--- a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_pressed_dark_am.9.png
+++ b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_pressed_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_pressed_light_am.9.png b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_pressed_light_am.9.png
index 92a298b..fbf042f 100644
--- a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_pressed_light_am.9.png
+++ b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_pressed_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/radiobutton_off_background.png b/core/res/res/drawable-xhdpi/radiobutton_off_background.png
index 384442f..46960e8 100644
--- a/core/res/res/drawable-xhdpi/radiobutton_off_background.png
+++ b/core/res/res/drawable-xhdpi/radiobutton_off_background.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/radiobutton_on_background.png b/core/res/res/drawable-xhdpi/radiobutton_on_background.png
index c65e4ff..cda5cec 100644
--- a/core/res/res/drawable-xhdpi/radiobutton_on_background.png
+++ b/core/res/res/drawable-xhdpi/radiobutton_on_background.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/rate_star_big_half.png b/core/res/res/drawable-xhdpi/rate_star_big_half.png
index 2ecb3b5..8674f4d 100644
--- a/core/res/res/drawable-xhdpi/rate_star_big_half.png
+++ b/core/res/res/drawable-xhdpi/rate_star_big_half.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/rate_star_big_half_holo_dark.png b/core/res/res/drawable-xhdpi/rate_star_big_half_holo_dark.png
index f9d3cec..b9cf4df 100644
--- a/core/res/res/drawable-xhdpi/rate_star_big_half_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/rate_star_big_half_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/rate_star_big_half_holo_light.png b/core/res/res/drawable-xhdpi/rate_star_big_half_holo_light.png
index bbdc70d3..4bc2b4b 100644
--- a/core/res/res/drawable-xhdpi/rate_star_big_half_holo_light.png
+++ b/core/res/res/drawable-xhdpi/rate_star_big_half_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/rate_star_big_off.png b/core/res/res/drawable-xhdpi/rate_star_big_off.png
index 8dae714..b2017bf 100644
--- a/core/res/res/drawable-xhdpi/rate_star_big_off.png
+++ b/core/res/res/drawable-xhdpi/rate_star_big_off.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/rate_star_big_off_holo_dark.png b/core/res/res/drawable-xhdpi/rate_star_big_off_holo_dark.png
index 34b94db..de9a5a6 100644
--- a/core/res/res/drawable-xhdpi/rate_star_big_off_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/rate_star_big_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/rate_star_big_off_holo_light.png b/core/res/res/drawable-xhdpi/rate_star_big_off_holo_light.png
index 34cb926..e217121 100644
--- a/core/res/res/drawable-xhdpi/rate_star_big_off_holo_light.png
+++ b/core/res/res/drawable-xhdpi/rate_star_big_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/rate_star_big_on.png b/core/res/res/drawable-xhdpi/rate_star_big_on.png
index 43633e1..c42c94b 100644
--- a/core/res/res/drawable-xhdpi/rate_star_big_on.png
+++ b/core/res/res/drawable-xhdpi/rate_star_big_on.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/rate_star_big_on_holo_dark.png b/core/res/res/drawable-xhdpi/rate_star_big_on_holo_dark.png
index 273fd16..05756fc 100644
--- a/core/res/res/drawable-xhdpi/rate_star_big_on_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/rate_star_big_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/rate_star_big_on_holo_light.png b/core/res/res/drawable-xhdpi/rate_star_big_on_holo_light.png
index dbd11bd..71cdb3d 100644
--- a/core/res/res/drawable-xhdpi/rate_star_big_on_holo_light.png
+++ b/core/res/res/drawable-xhdpi/rate_star_big_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/rate_star_med_half.png b/core/res/res/drawable-xhdpi/rate_star_med_half.png
index 44178c9..9932ea7 100644
--- a/core/res/res/drawable-xhdpi/rate_star_med_half.png
+++ b/core/res/res/drawable-xhdpi/rate_star_med_half.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/rate_star_med_half_holo_dark.png b/core/res/res/drawable-xhdpi/rate_star_med_half_holo_dark.png
index 013543e..6b4939a 100644
--- a/core/res/res/drawable-xhdpi/rate_star_med_half_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/rate_star_med_half_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/rate_star_med_half_holo_light.png b/core/res/res/drawable-xhdpi/rate_star_med_half_holo_light.png
index 801703f..ce8c1a4 100644
--- a/core/res/res/drawable-xhdpi/rate_star_med_half_holo_light.png
+++ b/core/res/res/drawable-xhdpi/rate_star_med_half_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/rate_star_med_off.png b/core/res/res/drawable-xhdpi/rate_star_med_off.png
index 101692d..d2b4ca8 100644
--- a/core/res/res/drawable-xhdpi/rate_star_med_off.png
+++ b/core/res/res/drawable-xhdpi/rate_star_med_off.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/rate_star_med_off_holo_dark.png b/core/res/res/drawable-xhdpi/rate_star_med_off_holo_dark.png
index d411e25..e9c7336 100644
--- a/core/res/res/drawable-xhdpi/rate_star_med_off_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/rate_star_med_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/rate_star_med_off_holo_light.png b/core/res/res/drawable-xhdpi/rate_star_med_off_holo_light.png
index 39f0fa2..a5b7e25 100644
--- a/core/res/res/drawable-xhdpi/rate_star_med_off_holo_light.png
+++ b/core/res/res/drawable-xhdpi/rate_star_med_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/rate_star_med_on.png b/core/res/res/drawable-xhdpi/rate_star_med_on.png
index a650d0d..dc7ac35 100644
--- a/core/res/res/drawable-xhdpi/rate_star_med_on.png
+++ b/core/res/res/drawable-xhdpi/rate_star_med_on.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/rate_star_med_on_holo_dark.png b/core/res/res/drawable-xhdpi/rate_star_med_on_holo_dark.png
index fdfe932..22d7eb8 100644
--- a/core/res/res/drawable-xhdpi/rate_star_med_on_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/rate_star_med_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/rate_star_med_on_holo_light.png b/core/res/res/drawable-xhdpi/rate_star_med_on_holo_light.png
index ca88d28..1224558 100644
--- a/core/res/res/drawable-xhdpi/rate_star_med_on_holo_light.png
+++ b/core/res/res/drawable-xhdpi/rate_star_med_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/rate_star_small_half.png b/core/res/res/drawable-xhdpi/rate_star_small_half.png
index a7e97a5..651a09c 100644
--- a/core/res/res/drawable-xhdpi/rate_star_small_half.png
+++ b/core/res/res/drawable-xhdpi/rate_star_small_half.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/rate_star_small_half_holo_dark.png b/core/res/res/drawable-xhdpi/rate_star_small_half_holo_dark.png
index 3d2a774..9cfa733 100644
--- a/core/res/res/drawable-xhdpi/rate_star_small_half_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/rate_star_small_half_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/rate_star_small_half_holo_light.png b/core/res/res/drawable-xhdpi/rate_star_small_half_holo_light.png
index 9221829f7..8453020 100644
--- a/core/res/res/drawable-xhdpi/rate_star_small_half_holo_light.png
+++ b/core/res/res/drawable-xhdpi/rate_star_small_half_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/rate_star_small_off.png b/core/res/res/drawable-xhdpi/rate_star_small_off.png
index 71140ac..99f9bbf 100644
--- a/core/res/res/drawable-xhdpi/rate_star_small_off.png
+++ b/core/res/res/drawable-xhdpi/rate_star_small_off.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/rate_star_small_off_holo_dark.png b/core/res/res/drawable-xhdpi/rate_star_small_off_holo_dark.png
index 346daa3..a30cf3d 100644
--- a/core/res/res/drawable-xhdpi/rate_star_small_off_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/rate_star_small_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/rate_star_small_off_holo_light.png b/core/res/res/drawable-xhdpi/rate_star_small_off_holo_light.png
index 4c2b62c..2d0f000 100644
--- a/core/res/res/drawable-xhdpi/rate_star_small_off_holo_light.png
+++ b/core/res/res/drawable-xhdpi/rate_star_small_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/rate_star_small_on.png b/core/res/res/drawable-xhdpi/rate_star_small_on.png
index ddfb876..8dab4a6 100644
--- a/core/res/res/drawable-xhdpi/rate_star_small_on.png
+++ b/core/res/res/drawable-xhdpi/rate_star_small_on.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/rate_star_small_on_holo_dark.png b/core/res/res/drawable-xhdpi/rate_star_small_on_holo_dark.png
index 9bf2466..ac16384 100644
--- a/core/res/res/drawable-xhdpi/rate_star_small_on_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/rate_star_small_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/rate_star_small_on_holo_light.png b/core/res/res/drawable-xhdpi/rate_star_small_on_holo_light.png
index 187eede..3431068 100644
--- a/core/res/res/drawable-xhdpi/rate_star_small_on_holo_light.png
+++ b/core/res/res/drawable-xhdpi/rate_star_small_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/recent_dialog_background.9.png b/core/res/res/drawable-xhdpi/recent_dialog_background.9.png
index 867e715..7a4af25 100644
--- a/core/res/res/drawable-xhdpi/recent_dialog_background.9.png
+++ b/core/res/res/drawable-xhdpi/recent_dialog_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/reticle.png b/core/res/res/drawable-xhdpi/reticle.png
index c28b70d..b1024d1 100644
--- a/core/res/res/drawable-xhdpi/reticle.png
+++ b/core/res/res/drawable-xhdpi/reticle.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrollbar_handle_accelerated_anim2.9.png b/core/res/res/drawable-xhdpi/scrollbar_handle_accelerated_anim2.9.png
index 70856c0..65a975d 100644
--- a/core/res/res/drawable-xhdpi/scrollbar_handle_accelerated_anim2.9.png
+++ b/core/res/res/drawable-xhdpi/scrollbar_handle_accelerated_anim2.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrollbar_handle_holo_dark.9.png b/core/res/res/drawable-xhdpi/scrollbar_handle_holo_dark.9.png
index 948072f..24ba634 100644
--- a/core/res/res/drawable-xhdpi/scrollbar_handle_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/scrollbar_handle_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrollbar_handle_holo_light.9.png b/core/res/res/drawable-xhdpi/scrollbar_handle_holo_light.9.png
index 461be3f..1538606 100644
--- a/core/res/res/drawable-xhdpi/scrollbar_handle_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/scrollbar_handle_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrollbar_handle_horizontal.9.png b/core/res/res/drawable-xhdpi/scrollbar_handle_horizontal.9.png
index be3e90e..4c016ed 100644
--- a/core/res/res/drawable-xhdpi/scrollbar_handle_horizontal.9.png
+++ b/core/res/res/drawable-xhdpi/scrollbar_handle_horizontal.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrollbar_handle_vertical.9.png b/core/res/res/drawable-xhdpi/scrollbar_handle_vertical.9.png
index 24789a5c..60c9614 100644
--- a/core/res/res/drawable-xhdpi/scrollbar_handle_vertical.9.png
+++ b/core/res/res/drawable-xhdpi/scrollbar_handle_vertical.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrubber_control_disabled_holo.png b/core/res/res/drawable-xhdpi/scrubber_control_disabled_holo.png
index 62be77c..2919204 100644
--- a/core/res/res/drawable-xhdpi/scrubber_control_disabled_holo.png
+++ b/core/res/res/drawable-xhdpi/scrubber_control_disabled_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrubber_control_focused_holo.png b/core/res/res/drawable-xhdpi/scrubber_control_focused_holo.png
index 754dd2f..4ae5ba7 100644
--- a/core/res/res/drawable-xhdpi/scrubber_control_focused_holo.png
+++ b/core/res/res/drawable-xhdpi/scrubber_control_focused_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrubber_control_normal_holo.png b/core/res/res/drawable-xhdpi/scrubber_control_normal_holo.png
index d546a73..288a0b2 100644
--- a/core/res/res/drawable-xhdpi/scrubber_control_normal_holo.png
+++ b/core/res/res/drawable-xhdpi/scrubber_control_normal_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrubber_control_on_mtrl_alpha.png b/core/res/res/drawable-xhdpi/scrubber_control_on_mtrl_alpha.png
index d018a7c..e557d44 100644
--- a/core/res/res/drawable-xhdpi/scrubber_control_on_mtrl_alpha.png
+++ b/core/res/res/drawable-xhdpi/scrubber_control_on_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrubber_control_on_pressed_mtrl_alpha.png b/core/res/res/drawable-xhdpi/scrubber_control_on_pressed_mtrl_alpha.png
index a7ed0f8..55e4b80 100644
--- a/core/res/res/drawable-xhdpi/scrubber_control_on_pressed_mtrl_alpha.png
+++ b/core/res/res/drawable-xhdpi/scrubber_control_on_pressed_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrubber_control_pressed_holo.png b/core/res/res/drawable-xhdpi/scrubber_control_pressed_holo.png
index 0b62072..4522a8b 100644
--- a/core/res/res/drawable-xhdpi/scrubber_control_pressed_holo.png
+++ b/core/res/res/drawable-xhdpi/scrubber_control_pressed_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrubber_primary_holo.9.png b/core/res/res/drawable-xhdpi/scrubber_primary_holo.9.png
index 3b0b241..e0c83dd 100644
--- a/core/res/res/drawable-xhdpi/scrubber_primary_holo.9.png
+++ b/core/res/res/drawable-xhdpi/scrubber_primary_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrubber_primary_mtrl_alpha.9.png b/core/res/res/drawable-xhdpi/scrubber_primary_mtrl_alpha.9.png
index 2b4734d..79b321a 100644
--- a/core/res/res/drawable-xhdpi/scrubber_primary_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xhdpi/scrubber_primary_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrubber_secondary_holo.9.png b/core/res/res/drawable-xhdpi/scrubber_secondary_holo.9.png
index 9099034..4f8d766 100644
--- a/core/res/res/drawable-xhdpi/scrubber_secondary_holo.9.png
+++ b/core/res/res/drawable-xhdpi/scrubber_secondary_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrubber_track_holo_dark.9.png b/core/res/res/drawable-xhdpi/scrubber_track_holo_dark.9.png
index bfb2048..d1a2070 100644
--- a/core/res/res/drawable-xhdpi/scrubber_track_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/scrubber_track_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrubber_track_holo_light.9.png b/core/res/res/drawable-xhdpi/scrubber_track_holo_light.9.png
index a7d396de2..80277ef 100644
--- a/core/res/res/drawable-xhdpi/scrubber_track_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/scrubber_track_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrubber_track_mtrl_alpha.9.png b/core/res/res/drawable-xhdpi/scrubber_track_mtrl_alpha.9.png
index 805cb29..118e8a4 100644
--- a/core/res/res/drawable-xhdpi/scrubber_track_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xhdpi/scrubber_track_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/search_dropdown_background.9.png b/core/res/res/drawable-xhdpi/search_dropdown_background.9.png
index 52761a7..6213c2f 100644
--- a/core/res/res/drawable-xhdpi/search_dropdown_background.9.png
+++ b/core/res/res/drawable-xhdpi/search_dropdown_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/search_plate.9.png b/core/res/res/drawable-xhdpi/search_plate.9.png
index f917cb6..f7ac1eb 100644
--- a/core/res/res/drawable-xhdpi/search_plate.9.png
+++ b/core/res/res/drawable-xhdpi/search_plate.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/search_plate_global.9.png b/core/res/res/drawable-xhdpi/search_plate_global.9.png
index 2c935ae..f5496ff 100644
--- a/core/res/res/drawable-xhdpi/search_plate_global.9.png
+++ b/core/res/res/drawable-xhdpi/search_plate_global.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/seek_thumb_normal.png b/core/res/res/drawable-xhdpi/seek_thumb_normal.png
index fb21fcb..c145370 100644
--- a/core/res/res/drawable-xhdpi/seek_thumb_normal.png
+++ b/core/res/res/drawable-xhdpi/seek_thumb_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/seek_thumb_pressed.png b/core/res/res/drawable-xhdpi/seek_thumb_pressed.png
index d3cb25a..0c953c9 100644
--- a/core/res/res/drawable-xhdpi/seek_thumb_pressed.png
+++ b/core/res/res/drawable-xhdpi/seek_thumb_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/seek_thumb_selected.png b/core/res/res/drawable-xhdpi/seek_thumb_selected.png
index 8227c1f..60f6f34 100644
--- a/core/res/res/drawable-xhdpi/seek_thumb_selected.png
+++ b/core/res/res/drawable-xhdpi/seek_thumb_selected.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/settings_header_raw.9.png b/core/res/res/drawable-xhdpi/settings_header_raw.9.png
index c248237..86208cf 100644
--- a/core/res/res/drawable-xhdpi/settings_header_raw.9.png
+++ b/core/res/res/drawable-xhdpi/settings_header_raw.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_16_inner_holo.png b/core/res/res/drawable-xhdpi/spinner_16_inner_holo.png
index 55e2329..17c0e4a 100644
--- a/core/res/res/drawable-xhdpi/spinner_16_inner_holo.png
+++ b/core/res/res/drawable-xhdpi/spinner_16_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_16_outer_holo.png b/core/res/res/drawable-xhdpi/spinner_16_outer_holo.png
index afd4bb9..a938735 100644
--- a/core/res/res/drawable-xhdpi/spinner_16_outer_holo.png
+++ b/core/res/res/drawable-xhdpi/spinner_16_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_48_inner_holo.png b/core/res/res/drawable-xhdpi/spinner_48_inner_holo.png
index 19517c4..eb87437 100644
--- a/core/res/res/drawable-xhdpi/spinner_48_inner_holo.png
+++ b/core/res/res/drawable-xhdpi/spinner_48_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_48_outer_holo.png b/core/res/res/drawable-xhdpi/spinner_48_outer_holo.png
index 14143c5..4661c17 100644
--- a/core/res/res/drawable-xhdpi/spinner_48_outer_holo.png
+++ b/core/res/res/drawable-xhdpi/spinner_48_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_76_inner_holo.png b/core/res/res/drawable-xhdpi/spinner_76_inner_holo.png
index 4c92e956..62de009 100644
--- a/core/res/res/drawable-xhdpi/spinner_76_inner_holo.png
+++ b/core/res/res/drawable-xhdpi/spinner_76_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_76_outer_holo.png b/core/res/res/drawable-xhdpi/spinner_76_outer_holo.png
index fe1d615..c90b061 100644
--- a/core/res/res/drawable-xhdpi/spinner_76_outer_holo.png
+++ b/core/res/res/drawable-xhdpi/spinner_76_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_ab_default_holo_dark_am.9.png b/core/res/res/drawable-xhdpi/spinner_ab_default_holo_dark_am.9.png
index c43293d..cc06b66 100644
--- a/core/res/res/drawable-xhdpi/spinner_ab_default_holo_dark_am.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_ab_default_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_ab_default_holo_light_am.9.png b/core/res/res/drawable-xhdpi/spinner_ab_default_holo_light_am.9.png
index 3dc481e..ea1fe0d 100644
--- a/core/res/res/drawable-xhdpi/spinner_ab_default_holo_light_am.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_ab_default_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_ab_disabled_holo_dark_am.9.png b/core/res/res/drawable-xhdpi/spinner_ab_disabled_holo_dark_am.9.png
index 9a7b173..d75ab78 100644
--- a/core/res/res/drawable-xhdpi/spinner_ab_disabled_holo_dark_am.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_ab_disabled_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_ab_disabled_holo_light_am.9.png b/core/res/res/drawable-xhdpi/spinner_ab_disabled_holo_light_am.9.png
index 6888fdc..10453f4 100644
--- a/core/res/res/drawable-xhdpi/spinner_ab_disabled_holo_light_am.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_ab_disabled_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_ab_focused_holo_dark_am.9.png b/core/res/res/drawable-xhdpi/spinner_ab_focused_holo_dark_am.9.png
index 9408b47..b55353d 100644
--- a/core/res/res/drawable-xhdpi/spinner_ab_focused_holo_dark_am.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_ab_focused_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_ab_focused_holo_light_am.9.png b/core/res/res/drawable-xhdpi/spinner_ab_focused_holo_light_am.9.png
index 1cb95d1..b8c2856 100644
--- a/core/res/res/drawable-xhdpi/spinner_ab_focused_holo_light_am.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_ab_focused_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_dark_am.9.png b/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_dark_am.9.png
index 2dab26f..a9b1800 100644
--- a/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_dark_am.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_light_am.9.png b/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_light_am.9.png
index d15cd51..ea61467 100644
--- a/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_light_am.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_black_16.png b/core/res/res/drawable-xhdpi/spinner_black_16.png
index 5b1422c..4f830d9 100644
--- a/core/res/res/drawable-xhdpi/spinner_black_16.png
+++ b/core/res/res/drawable-xhdpi/spinner_black_16.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_black_20.png b/core/res/res/drawable-xhdpi/spinner_black_20.png
index 5f53e38..f1fd52a 100644
--- a/core/res/res/drawable-xhdpi/spinner_black_20.png
+++ b/core/res/res/drawable-xhdpi/spinner_black_20.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_black_48.png b/core/res/res/drawable-xhdpi/spinner_black_48.png
index 3aab620..81ea5cc 100644
--- a/core/res/res/drawable-xhdpi/spinner_black_48.png
+++ b/core/res/res/drawable-xhdpi/spinner_black_48.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_black_76.png b/core/res/res/drawable-xhdpi/spinner_black_76.png
index 2968d8c..88ff1ef 100644
--- a/core/res/res/drawable-xhdpi/spinner_black_76.png
+++ b/core/res/res/drawable-xhdpi/spinner_black_76.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_default_holo_dark_am.9.png b/core/res/res/drawable-xhdpi/spinner_default_holo_dark_am.9.png
index fadfb5d..815ea25 100644
--- a/core/res/res/drawable-xhdpi/spinner_default_holo_dark_am.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_default_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_default_holo_light_am.9.png b/core/res/res/drawable-xhdpi/spinner_default_holo_light_am.9.png
index 5a4ec3b..018b7fc 100644
--- a/core/res/res/drawable-xhdpi/spinner_default_holo_light_am.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_default_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_disabled_holo_dark_am.9.png b/core/res/res/drawable-xhdpi/spinner_disabled_holo_dark_am.9.png
index 7c3c49b..3ea49d3 100644
--- a/core/res/res/drawable-xhdpi/spinner_disabled_holo_dark_am.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_disabled_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_disabled_holo_light_am.9.png b/core/res/res/drawable-xhdpi/spinner_disabled_holo_light_am.9.png
index fe54126..f8152f6 100644
--- a/core/res/res/drawable-xhdpi/spinner_disabled_holo_light_am.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_disabled_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_dropdown_background_down.9.png b/core/res/res/drawable-xhdpi/spinner_dropdown_background_down.9.png
index 7814354..ec1adad 100644
--- a/core/res/res/drawable-xhdpi/spinner_dropdown_background_down.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_dropdown_background_down.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_dropdown_background_up.9.png b/core/res/res/drawable-xhdpi/spinner_dropdown_background_up.9.png
index 17ee05c..c6c141d 100644
--- a/core/res/res/drawable-xhdpi/spinner_dropdown_background_up.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_dropdown_background_up.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_focused_holo_dark_am.9.png b/core/res/res/drawable-xhdpi/spinner_focused_holo_dark_am.9.png
index 9ea957e..6e3a6f4 100644
--- a/core/res/res/drawable-xhdpi/spinner_focused_holo_dark_am.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_focused_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_focused_holo_light_am.9.png b/core/res/res/drawable-xhdpi/spinner_focused_holo_light_am.9.png
index 8cb2fd8..6026ac4 100644
--- a/core/res/res/drawable-xhdpi/spinner_focused_holo_light_am.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_focused_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_normal.9.png b/core/res/res/drawable-xhdpi/spinner_normal.9.png
index 1ecf897..1994051 100644
--- a/core/res/res/drawable-xhdpi/spinner_normal.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_press.9.png b/core/res/res/drawable-xhdpi/spinner_press.9.png
index 87af85c..1b2db0f 100644
--- a/core/res/res/drawable-xhdpi/spinner_press.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_press.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_pressed_holo_dark_am.9.png b/core/res/res/drawable-xhdpi/spinner_pressed_holo_dark_am.9.png
index 2023a9d..78942de 100644
--- a/core/res/res/drawable-xhdpi/spinner_pressed_holo_dark_am.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_pressed_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_pressed_holo_light_am.9.png b/core/res/res/drawable-xhdpi/spinner_pressed_holo_light_am.9.png
index 3b066ae..931967c 100644
--- a/core/res/res/drawable-xhdpi/spinner_pressed_holo_light_am.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_pressed_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_select.9.png b/core/res/res/drawable-xhdpi/spinner_select.9.png
index 15b7a90..2e0d2e1 100644
--- a/core/res/res/drawable-xhdpi/spinner_select.9.png
+++ b/core/res/res/drawable-xhdpi/spinner_select.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_white_16.png b/core/res/res/drawable-xhdpi/spinner_white_16.png
index 69be752..cf29a8b 100644
--- a/core/res/res/drawable-xhdpi/spinner_white_16.png
+++ b/core/res/res/drawable-xhdpi/spinner_white_16.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_white_48.png b/core/res/res/drawable-xhdpi/spinner_white_48.png
index 7b196bc..796c62f 100644
--- a/core/res/res/drawable-xhdpi/spinner_white_48.png
+++ b/core/res/res/drawable-xhdpi/spinner_white_48.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_white_76.png b/core/res/res/drawable-xhdpi/spinner_white_76.png
index ba47005..26f7fbe 100644
--- a/core/res/res/drawable-xhdpi/spinner_white_76.png
+++ b/core/res/res/drawable-xhdpi/spinner_white_76.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/star_big_off.png b/core/res/res/drawable-xhdpi/star_big_off.png
index 8a17843..8fe36e6 100644
--- a/core/res/res/drawable-xhdpi/star_big_off.png
+++ b/core/res/res/drawable-xhdpi/star_big_off.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/star_big_on.png b/core/res/res/drawable-xhdpi/star_big_on.png
index 84f0596..19a95f1 100644
--- a/core/res/res/drawable-xhdpi/star_big_on.png
+++ b/core/res/res/drawable-xhdpi/star_big_on.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/star_off.png b/core/res/res/drawable-xhdpi/star_off.png
index 010ef9b..ae1ffe0 100644
--- a/core/res/res/drawable-xhdpi/star_off.png
+++ b/core/res/res/drawable-xhdpi/star_off.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/star_on.png b/core/res/res/drawable-xhdpi/star_on.png
index 01e077a..de3449d 100644
--- a/core/res/res/drawable-xhdpi/star_on.png
+++ b/core/res/res/drawable-xhdpi/star_on.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_ecb_mode.png b/core/res/res/drawable-xhdpi/stat_ecb_mode.png
index ce17494..68744a7 100644
--- a/core/res/res/drawable-xhdpi/stat_ecb_mode.png
+++ b/core/res/res/drawable-xhdpi/stat_ecb_mode.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_notify_car_mode.png b/core/res/res/drawable-xhdpi/stat_notify_car_mode.png
index 1f3a9cc..f50bab8c 100644
--- a/core/res/res/drawable-xhdpi/stat_notify_car_mode.png
+++ b/core/res/res/drawable-xhdpi/stat_notify_car_mode.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_notify_chat.png b/core/res/res/drawable-xhdpi/stat_notify_chat.png
index af85623..441a5b1 100644
--- a/core/res/res/drawable-xhdpi/stat_notify_chat.png
+++ b/core/res/res/drawable-xhdpi/stat_notify_chat.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_notify_disk_full.png b/core/res/res/drawable-xhdpi/stat_notify_disk_full.png
index 3fa330e..78e2c0a 100644
--- a/core/res/res/drawable-xhdpi/stat_notify_disk_full.png
+++ b/core/res/res/drawable-xhdpi/stat_notify_disk_full.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_notify_email_generic.png b/core/res/res/drawable-xhdpi/stat_notify_email_generic.png
index 07d297f..885ada9 100644
--- a/core/res/res/drawable-xhdpi/stat_notify_email_generic.png
+++ b/core/res/res/drawable-xhdpi/stat_notify_email_generic.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_notify_error.png b/core/res/res/drawable-xhdpi/stat_notify_error.png
index 2d0283e..2a00bee 100644
--- a/core/res/res/drawable-xhdpi/stat_notify_error.png
+++ b/core/res/res/drawable-xhdpi/stat_notify_error.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_notify_gmail.png b/core/res/res/drawable-xhdpi/stat_notify_gmail.png
index e1efa9b..6f56ffb 100644
--- a/core/res/res/drawable-xhdpi/stat_notify_gmail.png
+++ b/core/res/res/drawable-xhdpi/stat_notify_gmail.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_notify_missed_call.png b/core/res/res/drawable-xhdpi/stat_notify_missed_call.png
index 8719eff..476c872 100644
--- a/core/res/res/drawable-xhdpi/stat_notify_missed_call.png
+++ b/core/res/res/drawable-xhdpi/stat_notify_missed_call.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_notify_mmcc_indication_icn.png b/core/res/res/drawable-xhdpi/stat_notify_mmcc_indication_icn.png
index 5dfc89e..6a9412c 100644
--- a/core/res/res/drawable-xhdpi/stat_notify_mmcc_indication_icn.png
+++ b/core/res/res/drawable-xhdpi/stat_notify_mmcc_indication_icn.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_notify_more.png b/core/res/res/drawable-xhdpi/stat_notify_more.png
index 76c2c76..ea50cdc 100644
--- a/core/res/res/drawable-xhdpi/stat_notify_more.png
+++ b/core/res/res/drawable-xhdpi/stat_notify_more.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_notify_rssi_in_range.png b/core/res/res/drawable-xhdpi/stat_notify_rssi_in_range.png
index c0586d8..c564c8bd 100644
--- a/core/res/res/drawable-xhdpi/stat_notify_rssi_in_range.png
+++ b/core/res/res/drawable-xhdpi/stat_notify_rssi_in_range.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_notify_sdcard.png b/core/res/res/drawable-xhdpi/stat_notify_sdcard.png
index 7201213..b8ffa2d 100644
--- a/core/res/res/drawable-xhdpi/stat_notify_sdcard.png
+++ b/core/res/res/drawable-xhdpi/stat_notify_sdcard.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_notify_sdcard_prepare.png b/core/res/res/drawable-xhdpi/stat_notify_sdcard_prepare.png
index 648893b..92804de 100644
--- a/core/res/res/drawable-xhdpi/stat_notify_sdcard_prepare.png
+++ b/core/res/res/drawable-xhdpi/stat_notify_sdcard_prepare.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_notify_sdcard_usb.png b/core/res/res/drawable-xhdpi/stat_notify_sdcard_usb.png
index abd8b6e..8c50810 100644
--- a/core/res/res/drawable-xhdpi/stat_notify_sdcard_usb.png
+++ b/core/res/res/drawable-xhdpi/stat_notify_sdcard_usb.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_notify_sim_toolkit.png b/core/res/res/drawable-xhdpi/stat_notify_sim_toolkit.png
index 9e1df72..5652078 100644
--- a/core/res/res/drawable-xhdpi/stat_notify_sim_toolkit.png
+++ b/core/res/res/drawable-xhdpi/stat_notify_sim_toolkit.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_notify_sync.png b/core/res/res/drawable-xhdpi/stat_notify_sync.png
index b3bf21f..c1979bf 100644
--- a/core/res/res/drawable-xhdpi/stat_notify_sync.png
+++ b/core/res/res/drawable-xhdpi/stat_notify_sync.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_notify_sync_anim0.png b/core/res/res/drawable-xhdpi/stat_notify_sync_anim0.png
index b3bf21f..c1979bf 100644
--- a/core/res/res/drawable-xhdpi/stat_notify_sync_anim0.png
+++ b/core/res/res/drawable-xhdpi/stat_notify_sync_anim0.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_notify_sync_error.png b/core/res/res/drawable-xhdpi/stat_notify_sync_error.png
index 33582ef..b15259a 100644
--- a/core/res/res/drawable-xhdpi/stat_notify_sync_error.png
+++ b/core/res/res/drawable-xhdpi/stat_notify_sync_error.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_notify_voicemail.png b/core/res/res/drawable-xhdpi/stat_notify_voicemail.png
index fd88ac2..349fcbb 100644
--- a/core/res/res/drawable-xhdpi/stat_notify_voicemail.png
+++ b/core/res/res/drawable-xhdpi/stat_notify_voicemail.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_battery_0.png b/core/res/res/drawable-xhdpi/stat_sys_battery_0.png
index 50aa720..a649a23 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_battery_0.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_battery_0.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_battery_100.png b/core/res/res/drawable-xhdpi/stat_sys_battery_100.png
index 0aefc68..12b0189 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_battery_100.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_battery_100.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_battery_15.png b/core/res/res/drawable-xhdpi/stat_sys_battery_15.png
index 686ce51..3b2a388 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_battery_15.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_battery_15.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_battery_28.png b/core/res/res/drawable-xhdpi/stat_sys_battery_28.png
index 031546b..5e6e37c 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_battery_28.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_battery_28.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_battery_43.png b/core/res/res/drawable-xhdpi/stat_sys_battery_43.png
index d386987..e75c841 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_battery_43.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_battery_43.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_battery_57.png b/core/res/res/drawable-xhdpi/stat_sys_battery_57.png
index 51115df..e81acf4 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_battery_57.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_battery_57.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_battery_71.png b/core/res/res/drawable-xhdpi/stat_sys_battery_71.png
index ca4fd80..c67aa14 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_battery_71.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_battery_71.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_battery_85.png b/core/res/res/drawable-xhdpi/stat_sys_battery_85.png
index f32e9e1..4c19984 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_battery_85.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_battery_85.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_battery_charge_anim0.png b/core/res/res/drawable-xhdpi/stat_sys_battery_charge_anim0.png
index 1d9efe7..79bd5fa 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_battery_charge_anim0.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_battery_charge_anim0.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_battery_charge_anim100.png b/core/res/res/drawable-xhdpi/stat_sys_battery_charge_anim100.png
index c5debbf..b9dbbe2 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_battery_charge_anim100.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_battery_charge_anim100.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_battery_charge_anim15.png b/core/res/res/drawable-xhdpi/stat_sys_battery_charge_anim15.png
index 0b11fb1..17e84a5 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_battery_charge_anim15.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_battery_charge_anim15.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_battery_charge_anim28.png b/core/res/res/drawable-xhdpi/stat_sys_battery_charge_anim28.png
index 3d06ee2..9fbb16a 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_battery_charge_anim28.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_battery_charge_anim28.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_battery_charge_anim43.png b/core/res/res/drawable-xhdpi/stat_sys_battery_charge_anim43.png
index ea601e1..579e327 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_battery_charge_anim43.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_battery_charge_anim43.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_battery_charge_anim57.png b/core/res/res/drawable-xhdpi/stat_sys_battery_charge_anim57.png
index 843b0b4..b60e2fd 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_battery_charge_anim57.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_battery_charge_anim57.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_battery_charge_anim71.png b/core/res/res/drawable-xhdpi/stat_sys_battery_charge_anim71.png
index 213e3f1..75e0198 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_battery_charge_anim71.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_battery_charge_anim71.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_battery_charge_anim85.png b/core/res/res/drawable-xhdpi/stat_sys_battery_charge_anim85.png
index ca5c415..4113dd9 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_battery_charge_anim85.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_battery_charge_anim85.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_battery_unknown.png b/core/res/res/drawable-xhdpi/stat_sys_battery_unknown.png
index 7f156be..4b4483c 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_battery_unknown.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_battery_unknown.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_certificate_info.png b/core/res/res/drawable-xhdpi/stat_sys_certificate_info.png
index 3c93ea0..cda17433 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_certificate_info.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_certificate_info.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_data_bluetooth.png b/core/res/res/drawable-xhdpi/stat_sys_data_bluetooth.png
index 68cac47..559fc51 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_data_bluetooth.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_data_bluetooth.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_data_usb.png b/core/res/res/drawable-xhdpi/stat_sys_data_usb.png
index 57c1099..c5fd013 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_data_usb.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_data_usb.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_data_wimax_signal_3_fully.png b/core/res/res/drawable-xhdpi/stat_sys_data_wimax_signal_3_fully.png
index ec6bc54..273b8ee 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_data_wimax_signal_3_fully.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_data_wimax_signal_3_fully.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_data_wimax_signal_disconnected.png b/core/res/res/drawable-xhdpi/stat_sys_data_wimax_signal_disconnected.png
index 9fd4f33..db9f2ba 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_data_wimax_signal_disconnected.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_data_wimax_signal_disconnected.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_download_anim0.png b/core/res/res/drawable-xhdpi/stat_sys_download_anim0.png
index 73cbc96..df11658 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_download_anim0.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_download_anim0.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_download_anim1.png b/core/res/res/drawable-xhdpi/stat_sys_download_anim1.png
index 3e39abb..4239c9e 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_download_anim1.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_download_anim1.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_download_anim2.png b/core/res/res/drawable-xhdpi/stat_sys_download_anim2.png
index fc9b0de..e01db6e 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_download_anim2.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_download_anim2.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_download_anim3.png b/core/res/res/drawable-xhdpi/stat_sys_download_anim3.png
index 94bc012..ea3d32b 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_download_anim3.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_download_anim3.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_download_anim4.png b/core/res/res/drawable-xhdpi/stat_sys_download_anim4.png
index e6b5857..f04a916 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_download_anim4.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_download_anim4.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_download_anim5.png b/core/res/res/drawable-xhdpi/stat_sys_download_anim5.png
index f1df0c8..9869e5b 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_download_anim5.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_download_anim5.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_gps_on.png b/core/res/res/drawable-xhdpi/stat_sys_gps_on.png
index 8a6edfb..f872179 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_gps_on.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_gps_on.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_headset.png b/core/res/res/drawable-xhdpi/stat_sys_headset.png
index 4d447ab..114751f 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_headset.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_headset.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_phone_call.png b/core/res/res/drawable-xhdpi/stat_sys_phone_call.png
index e7a3981..3478fbf 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_phone_call.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_phone_call.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_phone_call_forward.png b/core/res/res/drawable-xhdpi/stat_sys_phone_call_forward.png
index 15c8dda..4d4f61f 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_phone_call_forward.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_phone_call_forward.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_phone_call_on_hold.png b/core/res/res/drawable-xhdpi/stat_sys_phone_call_on_hold.png
index d5a1531..7c1a881 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_phone_call_on_hold.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_phone_call_on_hold.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_r_signal_0_cdma.png b/core/res/res/drawable-xhdpi/stat_sys_r_signal_0_cdma.png
index 99ce378..bbf436b 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_r_signal_0_cdma.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_r_signal_0_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_r_signal_1_cdma.png b/core/res/res/drawable-xhdpi/stat_sys_r_signal_1_cdma.png
index e430114..fc71645 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_r_signal_1_cdma.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_r_signal_1_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_r_signal_2_cdma.png b/core/res/res/drawable-xhdpi/stat_sys_r_signal_2_cdma.png
index 4241896..b46bbb6 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_r_signal_2_cdma.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_r_signal_2_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_r_signal_3_cdma.png b/core/res/res/drawable-xhdpi/stat_sys_r_signal_3_cdma.png
index 3195fee..4a1a2d6 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_r_signal_3_cdma.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_r_signal_3_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_r_signal_4_cdma.png b/core/res/res/drawable-xhdpi/stat_sys_r_signal_4_cdma.png
index 3cb5463..6eb0c9b 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_r_signal_4_cdma.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_r_signal_4_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_ra_signal_0_cdma.png b/core/res/res/drawable-xhdpi/stat_sys_ra_signal_0_cdma.png
index 5f9a46b..26c20e0 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_ra_signal_0_cdma.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_ra_signal_0_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_ra_signal_1_cdma.png b/core/res/res/drawable-xhdpi/stat_sys_ra_signal_1_cdma.png
index da5d09c..5a74c98 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_ra_signal_1_cdma.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_ra_signal_1_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_ra_signal_2_cdma.png b/core/res/res/drawable-xhdpi/stat_sys_ra_signal_2_cdma.png
index 8cd6e08..92e6bc2 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_ra_signal_2_cdma.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_ra_signal_2_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_ra_signal_3_cdma.png b/core/res/res/drawable-xhdpi/stat_sys_ra_signal_3_cdma.png
index 6c68680..948dada 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_ra_signal_3_cdma.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_ra_signal_3_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_ra_signal_4_cdma.png b/core/res/res/drawable-xhdpi/stat_sys_ra_signal_4_cdma.png
index 5cf6e9c..df521b7 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_ra_signal_4_cdma.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_ra_signal_4_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_signal_0_cdma.png b/core/res/res/drawable-xhdpi/stat_sys_signal_0_cdma.png
index 28815f1..69fa2ff 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_signal_0_cdma.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_signal_0_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_signal_1_cdma.png b/core/res/res/drawable-xhdpi/stat_sys_signal_1_cdma.png
index 1643c10..c39e0ff 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_signal_1_cdma.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_signal_1_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_signal_2_cdma.png b/core/res/res/drawable-xhdpi/stat_sys_signal_2_cdma.png
index 0f5a147..a87c029 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_signal_2_cdma.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_signal_2_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_signal_3_cdma.png b/core/res/res/drawable-xhdpi/stat_sys_signal_3_cdma.png
index d37f761..54c9019 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_signal_3_cdma.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_signal_3_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_signal_4_cdma.png b/core/res/res/drawable-xhdpi/stat_sys_signal_4_cdma.png
index f4b835f..aae660b 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_signal_4_cdma.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_signal_4_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_signal_evdo_0.png b/core/res/res/drawable-xhdpi/stat_sys_signal_evdo_0.png
index dc5196c..96165d7 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_signal_evdo_0.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_signal_evdo_0.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_signal_evdo_1.png b/core/res/res/drawable-xhdpi/stat_sys_signal_evdo_1.png
index 5da3b3a..9e77b67 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_signal_evdo_1.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_signal_evdo_1.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_signal_evdo_2.png b/core/res/res/drawable-xhdpi/stat_sys_signal_evdo_2.png
index d17890d..49bc5f9 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_signal_evdo_2.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_signal_evdo_2.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_signal_evdo_3.png b/core/res/res/drawable-xhdpi/stat_sys_signal_evdo_3.png
index 2dbe7599..80c0e29 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_signal_evdo_3.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_signal_evdo_3.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_signal_evdo_4.png b/core/res/res/drawable-xhdpi/stat_sys_signal_evdo_4.png
index 796f9ed..b66337c 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_signal_evdo_4.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_signal_evdo_4.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_throttled.png b/core/res/res/drawable-xhdpi/stat_sys_throttled.png
index 043a1e3..09fed86 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_throttled.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_throttled.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_upload_anim0.png b/core/res/res/drawable-xhdpi/stat_sys_upload_anim0.png
index 2fbdaf8..779f6d5 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_upload_anim0.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_upload_anim0.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_upload_anim1.png b/core/res/res/drawable-xhdpi/stat_sys_upload_anim1.png
index e443f45..8e04e8e 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_upload_anim1.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_upload_anim1.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_upload_anim2.png b/core/res/res/drawable-xhdpi/stat_sys_upload_anim2.png
index cd0ca73..3c85cea 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_upload_anim2.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_upload_anim2.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_upload_anim3.png b/core/res/res/drawable-xhdpi/stat_sys_upload_anim3.png
index 8fb42f8..4fa0c7a 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_upload_anim3.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_upload_anim3.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_upload_anim4.png b/core/res/res/drawable-xhdpi/stat_sys_upload_anim4.png
index 2fb1802..d96bd61 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_upload_anim4.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_upload_anim4.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_upload_anim5.png b/core/res/res/drawable-xhdpi/stat_sys_upload_anim5.png
index c1d9db5..7f57129 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_upload_anim5.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_upload_anim5.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_vp_phone_call.png b/core/res/res/drawable-xhdpi/stat_sys_vp_phone_call.png
index af80481..ebb2489 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_vp_phone_call.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_vp_phone_call.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_vp_phone_call_on_hold.png b/core/res/res/drawable-xhdpi/stat_sys_vp_phone_call_on_hold.png
index 2ba1095..e851802 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_vp_phone_call_on_hold.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_vp_phone_call_on_hold.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_warning.png b/core/res/res/drawable-xhdpi/stat_sys_warning.png
index c7ac11f..ab1b014 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_warning.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_warning.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/status_bar_background.png b/core/res/res/drawable-xhdpi/status_bar_background.png
index 529904f..3da797a 100644
--- a/core/res/res/drawable-xhdpi/status_bar_background.png
+++ b/core/res/res/drawable-xhdpi/status_bar_background.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/status_bar_header_background.9.png b/core/res/res/drawable-xhdpi/status_bar_header_background.9.png
index efd3e97..800113e 100644
--- a/core/res/res/drawable-xhdpi/status_bar_header_background.9.png
+++ b/core/res/res/drawable-xhdpi/status_bar_header_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/status_bar_item_app_background_normal.9.png b/core/res/res/drawable-xhdpi/status_bar_item_app_background_normal.9.png
index 7f3d9db..b4fdddb 100644
--- a/core/res/res/drawable-xhdpi/status_bar_item_app_background_normal.9.png
+++ b/core/res/res/drawable-xhdpi/status_bar_item_app_background_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/status_bar_item_background_focus.9.png b/core/res/res/drawable-xhdpi/status_bar_item_background_focus.9.png
index 5d77613d..53a7012 100644
--- a/core/res/res/drawable-xhdpi/status_bar_item_background_focus.9.png
+++ b/core/res/res/drawable-xhdpi/status_bar_item_background_focus.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/status_bar_item_background_normal.9.png b/core/res/res/drawable-xhdpi/status_bar_item_background_normal.9.png
index 3b4959f..54a783b 100644
--- a/core/res/res/drawable-xhdpi/status_bar_item_background_normal.9.png
+++ b/core/res/res/drawable-xhdpi/status_bar_item_background_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/status_bar_item_background_pressed.9.png b/core/res/res/drawable-xhdpi/status_bar_item_background_pressed.9.png
index 70a000f..a12370d 100644
--- a/core/res/res/drawable-xhdpi/status_bar_item_background_pressed.9.png
+++ b/core/res/res/drawable-xhdpi/status_bar_item_background_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/statusbar_background.9.png b/core/res/res/drawable-xhdpi/statusbar_background.9.png
index e1a3a9b..b427397 100644
--- a/core/res/res/drawable-xhdpi/statusbar_background.9.png
+++ b/core/res/res/drawable-xhdpi/statusbar_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/submenu_arrow_nofocus.png b/core/res/res/drawable-xhdpi/submenu_arrow_nofocus.png
index 5e64030..37252fe4 100644
--- a/core/res/res/drawable-xhdpi/submenu_arrow_nofocus.png
+++ b/core/res/res/drawable-xhdpi/submenu_arrow_nofocus.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/switch_bg_disabled_holo_dark.9.png b/core/res/res/drawable-xhdpi/switch_bg_disabled_holo_dark.9.png
index b23070c..d47ca50 100644
--- a/core/res/res/drawable-xhdpi/switch_bg_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/switch_bg_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/switch_bg_disabled_holo_light.9.png b/core/res/res/drawable-xhdpi/switch_bg_disabled_holo_light.9.png
index 29f177a..9b2c234 100644
--- a/core/res/res/drawable-xhdpi/switch_bg_disabled_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/switch_bg_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/switch_bg_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/switch_bg_focused_holo_dark.9.png
index e85103d..b65f3b5 100644
--- a/core/res/res/drawable-xhdpi/switch_bg_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/switch_bg_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/switch_bg_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/switch_bg_focused_holo_light.9.png
index 75978bc..fff5222 100644
--- a/core/res/res/drawable-xhdpi/switch_bg_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/switch_bg_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/switch_bg_holo_dark.9.png b/core/res/res/drawable-xhdpi/switch_bg_holo_dark.9.png
index 732481e..42f9650 100644
--- a/core/res/res/drawable-xhdpi/switch_bg_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/switch_bg_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/switch_bg_holo_light.9.png b/core/res/res/drawable-xhdpi/switch_bg_holo_light.9.png
index aec616e..cd377bc 100644
--- a/core/res/res/drawable-xhdpi/switch_bg_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/switch_bg_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/switch_thumb_activated_holo_dark.9.png b/core/res/res/drawable-xhdpi/switch_thumb_activated_holo_dark.9.png
index ca48bd8..211f024 100644
--- a/core/res/res/drawable-xhdpi/switch_thumb_activated_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/switch_thumb_activated_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/switch_thumb_activated_holo_light.9.png b/core/res/res/drawable-xhdpi/switch_thumb_activated_holo_light.9.png
index ca48bd8..211f024 100644
--- a/core/res/res/drawable-xhdpi/switch_thumb_activated_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/switch_thumb_activated_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/switch_thumb_disabled_holo_dark.9.png b/core/res/res/drawable-xhdpi/switch_thumb_disabled_holo_dark.9.png
index c3d80f0..dd9b80c 100644
--- a/core/res/res/drawable-xhdpi/switch_thumb_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/switch_thumb_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/switch_thumb_disabled_holo_light.9.png b/core/res/res/drawable-xhdpi/switch_thumb_disabled_holo_light.9.png
index c3d80f0..dd9b80c 100644
--- a/core/res/res/drawable-xhdpi/switch_thumb_disabled_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/switch_thumb_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/switch_thumb_holo_dark.9.png b/core/res/res/drawable-xhdpi/switch_thumb_holo_dark.9.png
index df236df..098e6fd 100644
--- a/core/res/res/drawable-xhdpi/switch_thumb_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/switch_thumb_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/switch_thumb_holo_light.9.png b/core/res/res/drawable-xhdpi/switch_thumb_holo_light.9.png
index df236df..098e6fd 100644
--- a/core/res/res/drawable-xhdpi/switch_thumb_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/switch_thumb_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/switch_thumb_pressed_holo_dark.9.png b/core/res/res/drawable-xhdpi/switch_thumb_pressed_holo_dark.9.png
index dc69b12..3d80368 100644
--- a/core/res/res/drawable-xhdpi/switch_thumb_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/switch_thumb_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/switch_thumb_pressed_holo_light.9.png b/core/res/res/drawable-xhdpi/switch_thumb_pressed_holo_light.9.png
index 2370b63..75b170b 100644
--- a/core/res/res/drawable-xhdpi/switch_thumb_pressed_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/switch_thumb_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_action_add.png b/core/res/res/drawable-xhdpi/sym_action_add.png
index b0562c4..498d9f0 100644
--- a/core/res/res/drawable-xhdpi/sym_action_add.png
+++ b/core/res/res/drawable-xhdpi/sym_action_add.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_action_call.png b/core/res/res/drawable-xhdpi/sym_action_call.png
index e0de1e0..5bf4de3 100644
--- a/core/res/res/drawable-xhdpi/sym_action_call.png
+++ b/core/res/res/drawable-xhdpi/sym_action_call.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_action_chat.png b/core/res/res/drawable-xhdpi/sym_action_chat.png
index c0f2624..2a1bbc2 100644
--- a/core/res/res/drawable-xhdpi/sym_action_chat.png
+++ b/core/res/res/drawable-xhdpi/sym_action_chat.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_action_email.png b/core/res/res/drawable-xhdpi/sym_action_email.png
index 343a9c1..32363f1 100644
--- a/core/res/res/drawable-xhdpi/sym_action_email.png
+++ b/core/res/res/drawable-xhdpi/sym_action_email.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_call_incoming.png b/core/res/res/drawable-xhdpi/sym_call_incoming.png
index 738390a..c4b0200 100644
--- a/core/res/res/drawable-xhdpi/sym_call_incoming.png
+++ b/core/res/res/drawable-xhdpi/sym_call_incoming.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_call_missed.png b/core/res/res/drawable-xhdpi/sym_call_missed.png
index 2eb7aa4..1838f29 100644
--- a/core/res/res/drawable-xhdpi/sym_call_missed.png
+++ b/core/res/res/drawable-xhdpi/sym_call_missed.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_call_outgoing.png b/core/res/res/drawable-xhdpi/sym_call_outgoing.png
index 77f21e6..5308774 100644
--- a/core/res/res/drawable-xhdpi/sym_call_outgoing.png
+++ b/core/res/res/drawable-xhdpi/sym_call_outgoing.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_contact_card.png b/core/res/res/drawable-xhdpi/sym_contact_card.png
index aa65f1c..1e5f91b 100644
--- a/core/res/res/drawable-xhdpi/sym_contact_card.png
+++ b/core/res/res/drawable-xhdpi/sym_contact_card.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_delete.png b/core/res/res/drawable-xhdpi/sym_keyboard_delete.png
index 45c14aa..16f3fb2 100644
--- a/core/res/res/drawable-xhdpi/sym_keyboard_delete.png
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_delete.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_delete_dim.png b/core/res/res/drawable-xhdpi/sym_keyboard_delete_dim.png
index 2dac874..db98006e 100644
--- a/core/res/res/drawable-xhdpi/sym_keyboard_delete_dim.png
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_delete_dim.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_enter.png b/core/res/res/drawable-xhdpi/sym_keyboard_enter.png
index 3b034fd..96a0d6d 100644
--- a/core/res/res/drawable-xhdpi/sym_keyboard_enter.png
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_enter.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_feedback_delete.png b/core/res/res/drawable-xhdpi/sym_keyboard_feedback_delete.png
index 843cc82..2f76817 100644
--- a/core/res/res/drawable-xhdpi/sym_keyboard_feedback_delete.png
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_feedback_delete.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_feedback_ok.png b/core/res/res/drawable-xhdpi/sym_keyboard_feedback_ok.png
index 425452e..0136744 100644
--- a/core/res/res/drawable-xhdpi/sym_keyboard_feedback_ok.png
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_feedback_ok.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_feedback_return.png b/core/res/res/drawable-xhdpi/sym_keyboard_feedback_return.png
index d19e4dd..d15980ec 100644
--- a/core/res/res/drawable-xhdpi/sym_keyboard_feedback_return.png
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_feedback_return.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_feedback_shift.png b/core/res/res/drawable-xhdpi/sym_keyboard_feedback_shift.png
index 22df421..d907d09 100644
--- a/core/res/res/drawable-xhdpi/sym_keyboard_feedback_shift.png
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_feedback_shift.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_feedback_shift_locked.png b/core/res/res/drawable-xhdpi/sym_keyboard_feedback_shift_locked.png
index 30f3ead..7b27906 100644
--- a/core/res/res/drawable-xhdpi/sym_keyboard_feedback_shift_locked.png
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_feedback_shift_locked.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_feedback_space.png b/core/res/res/drawable-xhdpi/sym_keyboard_feedback_space.png
index 840da36..c8dd659 100644
--- a/core/res/res/drawable-xhdpi/sym_keyboard_feedback_space.png
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_feedback_space.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_num0_no_plus.png b/core/res/res/drawable-xhdpi/sym_keyboard_num0_no_plus.png
index cdd256d..5f1f19e 100644
--- a/core/res/res/drawable-xhdpi/sym_keyboard_num0_no_plus.png
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_num0_no_plus.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_num1.png b/core/res/res/drawable-xhdpi/sym_keyboard_num1.png
index d81d4b5..1c3a7ef 100644
--- a/core/res/res/drawable-xhdpi/sym_keyboard_num1.png
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_num1.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_num2.png b/core/res/res/drawable-xhdpi/sym_keyboard_num2.png
index 8ae9faf..021eab7 100644
--- a/core/res/res/drawable-xhdpi/sym_keyboard_num2.png
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_num2.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_num3.png b/core/res/res/drawable-xhdpi/sym_keyboard_num3.png
index ed6e90a..b91d0b7 100644
--- a/core/res/res/drawable-xhdpi/sym_keyboard_num3.png
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_num3.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_num4.png b/core/res/res/drawable-xhdpi/sym_keyboard_num4.png
index 5cff39f..8973499 100644
--- a/core/res/res/drawable-xhdpi/sym_keyboard_num4.png
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_num4.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_num5.png b/core/res/res/drawable-xhdpi/sym_keyboard_num5.png
index 1c9358e..befd82c 100644
--- a/core/res/res/drawable-xhdpi/sym_keyboard_num5.png
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_num5.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_num6.png b/core/res/res/drawable-xhdpi/sym_keyboard_num6.png
index 9a5cb6f..f69b762 100644
--- a/core/res/res/drawable-xhdpi/sym_keyboard_num6.png
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_num6.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_num7.png b/core/res/res/drawable-xhdpi/sym_keyboard_num7.png
index 1bd5c6b..52338c2 100644
--- a/core/res/res/drawable-xhdpi/sym_keyboard_num7.png
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_num7.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_num8.png b/core/res/res/drawable-xhdpi/sym_keyboard_num8.png
index 9a33152..e476e18 100644
--- a/core/res/res/drawable-xhdpi/sym_keyboard_num8.png
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_num8.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_num9.png b/core/res/res/drawable-xhdpi/sym_keyboard_num9.png
index caa3113..0643bab 100644
--- a/core/res/res/drawable-xhdpi/sym_keyboard_num9.png
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_num9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_ok.png b/core/res/res/drawable-xhdpi/sym_keyboard_ok.png
index 08a5eef..7ad9327 100644
--- a/core/res/res/drawable-xhdpi/sym_keyboard_ok.png
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_ok.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_ok_dim.png b/core/res/res/drawable-xhdpi/sym_keyboard_ok_dim.png
index 6a36618..7a9dc14 100644
--- a/core/res/res/drawable-xhdpi/sym_keyboard_ok_dim.png
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_ok_dim.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_return.png b/core/res/res/drawable-xhdpi/sym_keyboard_return.png
index b1e1ce9..1faba6c 100644
--- a/core/res/res/drawable-xhdpi/sym_keyboard_return.png
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_return.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_shift.png b/core/res/res/drawable-xhdpi/sym_keyboard_shift.png
index 6df4080..6d9a435 100644
--- a/core/res/res/drawable-xhdpi/sym_keyboard_shift.png
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_shift.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_shift_locked.png b/core/res/res/drawable-xhdpi/sym_keyboard_shift_locked.png
index 470196e..13e0191 100644
--- a/core/res/res/drawable-xhdpi/sym_keyboard_shift_locked.png
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_shift_locked.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_space.png b/core/res/res/drawable-xhdpi/sym_keyboard_space.png
index cce2845..032860d 100644
--- a/core/res/res/drawable-xhdpi/sym_keyboard_space.png
+++ b/core/res/res/drawable-xhdpi/sym_keyboard_space.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/tab_bottom_holo.9.png b/core/res/res/drawable-xhdpi/tab_bottom_holo.9.png
index 712dd22..b4ee271 100644
--- a/core/res/res/drawable-xhdpi/tab_bottom_holo.9.png
+++ b/core/res/res/drawable-xhdpi/tab_bottom_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/tab_focus.9.png b/core/res/res/drawable-xhdpi/tab_focus.9.png
index 737d2c4..2facd7a 100644
--- a/core/res/res/drawable-xhdpi/tab_focus.9.png
+++ b/core/res/res/drawable-xhdpi/tab_focus.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/tab_focus_bar_left.9.png b/core/res/res/drawable-xhdpi/tab_focus_bar_left.9.png
index e879e37..8a91e3f 100644
--- a/core/res/res/drawable-xhdpi/tab_focus_bar_left.9.png
+++ b/core/res/res/drawable-xhdpi/tab_focus_bar_left.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/tab_focus_bar_right.9.png b/core/res/res/drawable-xhdpi/tab_focus_bar_right.9.png
index e879e37..8a91e3f 100644
--- a/core/res/res/drawable-xhdpi/tab_focus_bar_right.9.png
+++ b/core/res/res/drawable-xhdpi/tab_focus_bar_right.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/tab_indicator_mtrl_alpha.9.png b/core/res/res/drawable-xhdpi/tab_indicator_mtrl_alpha.9.png
index 5610d8c..27a981c 100644
--- a/core/res/res/drawable-xhdpi/tab_indicator_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xhdpi/tab_indicator_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/tab_press.9.png b/core/res/res/drawable-xhdpi/tab_press.9.png
index 78b43db..d677c54 100644
--- a/core/res/res/drawable-xhdpi/tab_press.9.png
+++ b/core/res/res/drawable-xhdpi/tab_press.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/tab_press_bar_left.9.png b/core/res/res/drawable-xhdpi/tab_press_bar_left.9.png
index c5f44f3..92bb0fd 100644
--- a/core/res/res/drawable-xhdpi/tab_press_bar_left.9.png
+++ b/core/res/res/drawable-xhdpi/tab_press_bar_left.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/tab_press_bar_right.9.png b/core/res/res/drawable-xhdpi/tab_press_bar_right.9.png
index c5f44f3..92bb0fd 100644
--- a/core/res/res/drawable-xhdpi/tab_press_bar_right.9.png
+++ b/core/res/res/drawable-xhdpi/tab_press_bar_right.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/tab_pressed_holo.9.png b/core/res/res/drawable-xhdpi/tab_pressed_holo.9.png
index c221975..647cabf 100644
--- a/core/res/res/drawable-xhdpi/tab_pressed_holo.9.png
+++ b/core/res/res/drawable-xhdpi/tab_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/tab_selected.9.png b/core/res/res/drawable-xhdpi/tab_selected.9.png
index fba5ee4..334f109 100644
--- a/core/res/res/drawable-xhdpi/tab_selected.9.png
+++ b/core/res/res/drawable-xhdpi/tab_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/tab_selected_bar_left.9.png b/core/res/res/drawable-xhdpi/tab_selected_bar_left.9.png
index 53efbb4..c56c112 100644
--- a/core/res/res/drawable-xhdpi/tab_selected_bar_left.9.png
+++ b/core/res/res/drawable-xhdpi/tab_selected_bar_left.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/tab_selected_bar_left_v4.9.png b/core/res/res/drawable-xhdpi/tab_selected_bar_left_v4.9.png
index eec4ddb..07a7982 100644
--- a/core/res/res/drawable-xhdpi/tab_selected_bar_left_v4.9.png
+++ b/core/res/res/drawable-xhdpi/tab_selected_bar_left_v4.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/tab_selected_bar_right.9.png b/core/res/res/drawable-xhdpi/tab_selected_bar_right.9.png
index 53efbb4..c56c112 100644
--- a/core/res/res/drawable-xhdpi/tab_selected_bar_right.9.png
+++ b/core/res/res/drawable-xhdpi/tab_selected_bar_right.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/tab_selected_bar_right_v4.9.png b/core/res/res/drawable-xhdpi/tab_selected_bar_right_v4.9.png
index eec4ddb..07a7982 100644
--- a/core/res/res/drawable-xhdpi/tab_selected_bar_right_v4.9.png
+++ b/core/res/res/drawable-xhdpi/tab_selected_bar_right_v4.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/tab_selected_focused_holo.9.png b/core/res/res/drawable-xhdpi/tab_selected_focused_holo.9.png
index 03cfb09..ca81880 100644
--- a/core/res/res/drawable-xhdpi/tab_selected_focused_holo.9.png
+++ b/core/res/res/drawable-xhdpi/tab_selected_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/tab_selected_holo.9.png b/core/res/res/drawable-xhdpi/tab_selected_holo.9.png
index e4229f2..31fb7a6 100644
--- a/core/res/res/drawable-xhdpi/tab_selected_holo.9.png
+++ b/core/res/res/drawable-xhdpi/tab_selected_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/tab_selected_pressed_holo.9.png b/core/res/res/drawable-xhdpi/tab_selected_pressed_holo.9.png
index f13a194..ee01d44 100644
--- a/core/res/res/drawable-xhdpi/tab_selected_pressed_holo.9.png
+++ b/core/res/res/drawable-xhdpi/tab_selected_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/tab_selected_v4.9.png b/core/res/res/drawable-xhdpi/tab_selected_v4.9.png
index f1f4ec6..13e40d1 100644
--- a/core/res/res/drawable-xhdpi/tab_selected_v4.9.png
+++ b/core/res/res/drawable-xhdpi/tab_selected_v4.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/tab_unselected.9.png b/core/res/res/drawable-xhdpi/tab_unselected.9.png
index 3171701..aaa2433 100644
--- a/core/res/res/drawable-xhdpi/tab_unselected.9.png
+++ b/core/res/res/drawable-xhdpi/tab_unselected.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/tab_unselected_focused_holo.9.png b/core/res/res/drawable-xhdpi/tab_unselected_focused_holo.9.png
index f3a5cbd..16d8470 100644
--- a/core/res/res/drawable-xhdpi/tab_unselected_focused_holo.9.png
+++ b/core/res/res/drawable-xhdpi/tab_unselected_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/tab_unselected_holo.9.png b/core/res/res/drawable-xhdpi/tab_unselected_holo.9.png
index 9465173..b5afbb6 100644
--- a/core/res/res/drawable-xhdpi/tab_unselected_holo.9.png
+++ b/core/res/res/drawable-xhdpi/tab_unselected_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/tab_unselected_pressed_holo.9.png b/core/res/res/drawable-xhdpi/tab_unselected_pressed_holo.9.png
index 358ce26..bb71047 100644
--- a/core/res/res/drawable-xhdpi/tab_unselected_pressed_holo.9.png
+++ b/core/res/res/drawable-xhdpi/tab_unselected_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/tab_unselected_v4.9.png b/core/res/res/drawable-xhdpi/tab_unselected_v4.9.png
index 1df8c3a..2fee71b 100644
--- a/core/res/res/drawable-xhdpi/tab_unselected_v4.9.png
+++ b/core/res/res/drawable-xhdpi/tab_unselected_v4.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/text_edit_paste_window.9.png b/core/res/res/drawable-xhdpi/text_edit_paste_window.9.png
index a6e199a..79aa737 100644
--- a/core/res/res/drawable-xhdpi/text_edit_paste_window.9.png
+++ b/core/res/res/drawable-xhdpi/text_edit_paste_window.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/text_edit_side_paste_window.9.png b/core/res/res/drawable-xhdpi/text_edit_side_paste_window.9.png
index f96ff01..cd4bec9 100644
--- a/core/res/res/drawable-xhdpi/text_edit_side_paste_window.9.png
+++ b/core/res/res/drawable-xhdpi/text_edit_side_paste_window.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/text_edit_suggestions_window.9.png b/core/res/res/drawable-xhdpi/text_edit_suggestions_window.9.png
index a6e199a..79aa737 100644
--- a/core/res/res/drawable-xhdpi/text_edit_suggestions_window.9.png
+++ b/core/res/res/drawable-xhdpi/text_edit_suggestions_window.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/text_select_handle_left_mtrl_alpha.png b/core/res/res/drawable-xhdpi/text_select_handle_left_mtrl_alpha.png
index b5c2a91..67e9e12 100644
--- a/core/res/res/drawable-xhdpi/text_select_handle_left_mtrl_alpha.png
+++ b/core/res/res/drawable-xhdpi/text_select_handle_left_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/text_select_handle_middle_mtrl_alpha.png b/core/res/res/drawable-xhdpi/text_select_handle_middle_mtrl_alpha.png
index c1ca323..e0bcc7b 100644
--- a/core/res/res/drawable-xhdpi/text_select_handle_middle_mtrl_alpha.png
+++ b/core/res/res/drawable-xhdpi/text_select_handle_middle_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/text_select_handle_right_mtrl_alpha.png b/core/res/res/drawable-xhdpi/text_select_handle_right_mtrl_alpha.png
index 6c6185c..52bc4d1 100644
--- a/core/res/res/drawable-xhdpi/text_select_handle_right_mtrl_alpha.png
+++ b/core/res/res/drawable-xhdpi/text_select_handle_right_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_activated_holo_dark.9.png b/core/res/res/drawable-xhdpi/textfield_activated_holo_dark.9.png
index 653b7dc..1c9458d 100644
--- a/core/res/res/drawable-xhdpi/textfield_activated_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_activated_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_activated_holo_light.9.png b/core/res/res/drawable-xhdpi/textfield_activated_holo_light.9.png
index 08fcc5e..1c9458d 100644
--- a/core/res/res/drawable-xhdpi/textfield_activated_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_activated_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_activated_mtrl_alpha.9.png b/core/res/res/drawable-xhdpi/textfield_activated_mtrl_alpha.9.png
index 8c617fd..2e827f0 100644
--- a/core/res/res/drawable-xhdpi/textfield_activated_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_activated_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_default.9.png b/core/res/res/drawable-xhdpi/textfield_default.9.png
index f084f47..0132210 100644
--- a/core/res/res/drawable-xhdpi/textfield_default.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_default_holo_dark.9.png b/core/res/res/drawable-xhdpi/textfield_default_holo_dark.9.png
index 3f63c3fc..9b7b982 100644
--- a/core/res/res/drawable-xhdpi/textfield_default_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_default_holo_light.9.png b/core/res/res/drawable-xhdpi/textfield_default_holo_light.9.png
index dbb9924..5737561 100644
--- a/core/res/res/drawable-xhdpi/textfield_default_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_default_mtrl_alpha.9.png b/core/res/res/drawable-xhdpi/textfield_default_mtrl_alpha.9.png
index 240ef7b..83db9ae 100644
--- a/core/res/res/drawable-xhdpi/textfield_default_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_default_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_disabled.9.png b/core/res/res/drawable-xhdpi/textfield_disabled.9.png
index 1940051..7eb4224 100644
--- a/core/res/res/drawable-xhdpi/textfield_disabled.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_disabled_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/textfield_disabled_focused_holo_dark.9.png
index a9767fc..28a4467 100644
--- a/core/res/res/drawable-xhdpi/textfield_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_disabled_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/textfield_disabled_focused_holo_light.9.png
index 40a28cf..3ff7b59 100644
--- a/core/res/res/drawable-xhdpi/textfield_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_disabled_holo_dark.9.png b/core/res/res/drawable-xhdpi/textfield_disabled_holo_dark.9.png
index d78b10d..cdf7cdf 100644
--- a/core/res/res/drawable-xhdpi/textfield_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_disabled_holo_light.9.png b/core/res/res/drawable-xhdpi/textfield_disabled_holo_light.9.png
index 4ffdd86..d90b7df 100644
--- a/core/res/res/drawable-xhdpi/textfield_disabled_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_disabled_selected.9.png b/core/res/res/drawable-xhdpi/textfield_disabled_selected.9.png
index 335bee6..fdddbe1 100644
--- a/core/res/res/drawable-xhdpi/textfield_disabled_selected.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_disabled_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/textfield_focused_holo_dark.9.png
index 3ed03f3..6264df5 100644
--- a/core/res/res/drawable-xhdpi/textfield_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/textfield_focused_holo_light.9.png
index 3ed03f3..6264df5 100644
--- a/core/res/res/drawable-xhdpi/textfield_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_multiline_activated_holo_dark.9.png b/core/res/res/drawable-xhdpi/textfield_multiline_activated_holo_dark.9.png
index e12da1b..1c9458d 100644
--- a/core/res/res/drawable-xhdpi/textfield_multiline_activated_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_multiline_activated_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_multiline_activated_holo_light.9.png b/core/res/res/drawable-xhdpi/textfield_multiline_activated_holo_light.9.png
index 557788b..1c9458d 100644
--- a/core/res/res/drawable-xhdpi/textfield_multiline_activated_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_multiline_activated_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_multiline_default_holo_dark.9.png b/core/res/res/drawable-xhdpi/textfield_multiline_default_holo_dark.9.png
index 9a367c9..9b7b982 100644
--- a/core/res/res/drawable-xhdpi/textfield_multiline_default_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_multiline_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_multiline_default_holo_light.9.png b/core/res/res/drawable-xhdpi/textfield_multiline_default_holo_light.9.png
index 147ac58..5737561 100644
--- a/core/res/res/drawable-xhdpi/textfield_multiline_default_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_multiline_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_multiline_disabled_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/textfield_multiline_disabled_focused_holo_dark.9.png
index f89316a..56517ef 100644
--- a/core/res/res/drawable-xhdpi/textfield_multiline_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_multiline_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_multiline_disabled_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/textfield_multiline_disabled_focused_holo_light.9.png
index 06173a4..3ff7b59 100644
--- a/core/res/res/drawable-xhdpi/textfield_multiline_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_multiline_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_multiline_disabled_holo_dark.9.png b/core/res/res/drawable-xhdpi/textfield_multiline_disabled_holo_dark.9.png
index 1463e5d..cdf7cdf 100644
--- a/core/res/res/drawable-xhdpi/textfield_multiline_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_multiline_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_multiline_disabled_holo_light.9.png b/core/res/res/drawable-xhdpi/textfield_multiline_disabled_holo_light.9.png
index e1c7e8c..d90b7df 100644
--- a/core/res/res/drawable-xhdpi/textfield_multiline_disabled_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_multiline_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_multiline_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/textfield_multiline_focused_holo_dark.9.png
index 9247353..ecacf20 100644
--- a/core/res/res/drawable-xhdpi/textfield_multiline_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_multiline_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_multiline_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/textfield_multiline_focused_holo_light.9.png
index cab8e9f..cda7a9c 100644
--- a/core/res/res/drawable-xhdpi/textfield_multiline_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_multiline_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_activated_mtrl_alpha.9.png b/core/res/res/drawable-xhdpi/textfield_search_activated_mtrl_alpha.9.png
index 33c1035..0321dd8 100644
--- a/core/res/res/drawable-xhdpi/textfield_search_activated_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_search_activated_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_default.9.png b/core/res/res/drawable-xhdpi/textfield_search_default.9.png
index ad4b935..56901ea 100644
--- a/core/res/res/drawable-xhdpi/textfield_search_default.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_search_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_default_holo_dark.9.png b/core/res/res/drawable-xhdpi/textfield_search_default_holo_dark.9.png
index 8fdbbf3..c5e88a7 100644
--- a/core/res/res/drawable-xhdpi/textfield_search_default_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_search_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_default_holo_light.9.png b/core/res/res/drawable-xhdpi/textfield_search_default_holo_light.9.png
index 4e9ae43..61ee5a4 100644
--- a/core/res/res/drawable-xhdpi/textfield_search_default_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_search_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_default_mtrl_alpha.9.png b/core/res/res/drawable-xhdpi/textfield_search_default_mtrl_alpha.9.png
index 0226f84..8d8c763 100644
--- a/core/res/res/drawable-xhdpi/textfield_search_default_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_search_default_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_empty_default.9.png b/core/res/res/drawable-xhdpi/textfield_search_empty_default.9.png
index 0c60f9e..339c3cc 100644
--- a/core/res/res/drawable-xhdpi/textfield_search_empty_default.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_search_empty_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_empty_pressed.9.png b/core/res/res/drawable-xhdpi/textfield_search_empty_pressed.9.png
index 741bed9..9e4fe38 100644
--- a/core/res/res/drawable-xhdpi/textfield_search_empty_pressed.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_search_empty_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_empty_selected.9.png b/core/res/res/drawable-xhdpi/textfield_search_empty_selected.9.png
index 24ea6cf..b7c50cb 100644
--- a/core/res/res/drawable-xhdpi/textfield_search_empty_selected.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_search_empty_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_pressed.9.png b/core/res/res/drawable-xhdpi/textfield_search_pressed.9.png
index 815785c..c755bb4 100644
--- a/core/res/res/drawable-xhdpi/textfield_search_pressed.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_search_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_right_default_holo_dark.9.png b/core/res/res/drawable-xhdpi/textfield_search_right_default_holo_dark.9.png
index 98f4871..b794a2f 100644
--- a/core/res/res/drawable-xhdpi/textfield_search_right_default_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_search_right_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_right_default_holo_light.9.png b/core/res/res/drawable-xhdpi/textfield_search_right_default_holo_light.9.png
index 733373e..c77f6b2 100644
--- a/core/res/res/drawable-xhdpi/textfield_search_right_default_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_search_right_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_right_selected_holo_dark.9.png b/core/res/res/drawable-xhdpi/textfield_search_right_selected_holo_dark.9.png
index 0c6bb03..e283cdf 100644
--- a/core/res/res/drawable-xhdpi/textfield_search_right_selected_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_search_right_selected_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_right_selected_holo_light.9.png b/core/res/res/drawable-xhdpi/textfield_search_right_selected_holo_light.9.png
index 0c6bb03..e283cdf 100644
--- a/core/res/res/drawable-xhdpi/textfield_search_right_selected_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_search_right_selected_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_selected.9.png b/core/res/res/drawable-xhdpi/textfield_search_selected.9.png
index f009cdb..379de20 100644
--- a/core/res/res/drawable-xhdpi/textfield_search_selected.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_search_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_selected_holo_light.9.png b/core/res/res/drawable-xhdpi/textfield_search_selected_holo_light.9.png
index 1743da6..d2e4c10 100644
--- a/core/res/res/drawable-xhdpi/textfield_search_selected_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_search_selected_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_selected.9.png b/core/res/res/drawable-xhdpi/textfield_selected.9.png
index 963efde..ad3614c 100644
--- a/core/res/res/drawable-xhdpi/textfield_selected.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/title_bar_medium.9.png b/core/res/res/drawable-xhdpi/title_bar_medium.9.png
index 109c017..d06e017 100644
--- a/core/res/res/drawable-xhdpi/title_bar_medium.9.png
+++ b/core/res/res/drawable-xhdpi/title_bar_medium.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/title_bar_portrait.9.png b/core/res/res/drawable-xhdpi/title_bar_portrait.9.png
index 3c91a4a..6caa694 100644
--- a/core/res/res/drawable-xhdpi/title_bar_portrait.9.png
+++ b/core/res/res/drawable-xhdpi/title_bar_portrait.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/title_bar_tall.9.png b/core/res/res/drawable-xhdpi/title_bar_tall.9.png
index e986db1..6e2ea9b 100644
--- a/core/res/res/drawable-xhdpi/title_bar_tall.9.png
+++ b/core/res/res/drawable-xhdpi/title_bar_tall.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/transportcontrol_bg.9.png b/core/res/res/drawable-xhdpi/transportcontrol_bg.9.png
index b690a2a..c29111f 100644
--- a/core/res/res/drawable-xhdpi/transportcontrol_bg.9.png
+++ b/core/res/res/drawable-xhdpi/transportcontrol_bg.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/unknown_image.png b/core/res/res/drawable-xhdpi/unknown_image.png
index 0a9f643..b6633d5 100644
--- a/core/res/res/drawable-xhdpi/unknown_image.png
+++ b/core/res/res/drawable-xhdpi/unknown_image.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_14w.png b/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_14w.png
index 7f7ca14..119207b 100644
--- a/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_14w.png
+++ b/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_14w.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_15w.png b/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_15w.png
index 52120b8..b89c86a 100644
--- a/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_15w.png
+++ b/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_15w.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_16w.png b/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_16w.png
index d6e9be9..7528731 100644
--- a/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_16w.png
+++ b/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_16w.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_17w.png b/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_17w.png
index 8d76393..dba351f 100644
--- a/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_17w.png
+++ b/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_17w.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_18w.png b/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_18w.png
index ca9c66e..ab7b1df 100644
--- a/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_18w.png
+++ b/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_18w.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/watch_switch_track_mtrl.png b/core/res/res/drawable-xhdpi/watch_switch_track_mtrl.png
index 1aa5442..2caac58 100644
--- a/core/res/res/drawable-xhdpi/watch_switch_track_mtrl.png
+++ b/core/res/res/drawable-xhdpi/watch_switch_track_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/zoom_plate.9.png b/core/res/res/drawable-xhdpi/zoom_plate.9.png
index 797215b..bd8ec34 100644
--- a/core/res/res/drawable-xhdpi/zoom_plate.9.png
+++ b/core/res/res/drawable-xhdpi/zoom_plate.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_bottom_solid_dark_holo.9.png b/core/res/res/drawable-xxhdpi/ab_bottom_solid_dark_holo.9.png
index 8358392..4d41e1d 100644
--- a/core/res/res/drawable-xxhdpi/ab_bottom_solid_dark_holo.9.png
+++ b/core/res/res/drawable-xxhdpi/ab_bottom_solid_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_bottom_solid_inverse_holo.9.png b/core/res/res/drawable-xxhdpi/ab_bottom_solid_inverse_holo.9.png
index 8c6e40c..563b0cf 100644
--- a/core/res/res/drawable-xxhdpi/ab_bottom_solid_inverse_holo.9.png
+++ b/core/res/res/drawable-xxhdpi/ab_bottom_solid_inverse_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_bottom_solid_light_holo.9.png b/core/res/res/drawable-xxhdpi/ab_bottom_solid_light_holo.9.png
index f6c33dc..7e2a087 100644
--- a/core/res/res/drawable-xxhdpi/ab_bottom_solid_light_holo.9.png
+++ b/core/res/res/drawable-xxhdpi/ab_bottom_solid_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_bottom_transparent_dark_holo.9.png b/core/res/res/drawable-xxhdpi/ab_bottom_transparent_dark_holo.9.png
index f32ca94..db4da31 100644
--- a/core/res/res/drawable-xxhdpi/ab_bottom_transparent_dark_holo.9.png
+++ b/core/res/res/drawable-xxhdpi/ab_bottom_transparent_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_bottom_transparent_light_holo.9.png b/core/res/res/drawable-xxhdpi/ab_bottom_transparent_light_holo.9.png
index da69ea5..072116a 100644
--- a/core/res/res/drawable-xxhdpi/ab_bottom_transparent_light_holo.9.png
+++ b/core/res/res/drawable-xxhdpi/ab_bottom_transparent_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_share_pack_holo_dark.9.png b/core/res/res/drawable-xxhdpi/ab_share_pack_holo_dark.9.png
index 18269a9c..c9b803c 100644
--- a/core/res/res/drawable-xxhdpi/ab_share_pack_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/ab_share_pack_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_share_pack_holo_light.9.png b/core/res/res/drawable-xxhdpi/ab_share_pack_holo_light.9.png
index 469f736..a6481f3 100644
--- a/core/res/res/drawable-xxhdpi/ab_share_pack_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/ab_share_pack_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_share_pack_mtrl_alpha.9.png b/core/res/res/drawable-xxhdpi/ab_share_pack_mtrl_alpha.9.png
index 469f736..a6481f3 100644
--- a/core/res/res/drawable-xxhdpi/ab_share_pack_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xxhdpi/ab_share_pack_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_solid_dark_holo.9.png b/core/res/res/drawable-xxhdpi/ab_solid_dark_holo.9.png
index 48be5cc..47323340 100644
--- a/core/res/res/drawable-xxhdpi/ab_solid_dark_holo.9.png
+++ b/core/res/res/drawable-xxhdpi/ab_solid_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_solid_light_holo.9.png b/core/res/res/drawable-xxhdpi/ab_solid_light_holo.9.png
index 2e49b8d..d7218b6 100644
--- a/core/res/res/drawable-xxhdpi/ab_solid_light_holo.9.png
+++ b/core/res/res/drawable-xxhdpi/ab_solid_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_solid_shadow_holo.9.png b/core/res/res/drawable-xxhdpi/ab_solid_shadow_holo.9.png
index 8071886..8f81264 100644
--- a/core/res/res/drawable-xxhdpi/ab_solid_shadow_holo.9.png
+++ b/core/res/res/drawable-xxhdpi/ab_solid_shadow_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_solid_shadow_mtrl_alpha.9.png b/core/res/res/drawable-xxhdpi/ab_solid_shadow_mtrl_alpha.9.png
index e8a94dc..21560bd 100644
--- a/core/res/res/drawable-xxhdpi/ab_solid_shadow_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xxhdpi/ab_solid_shadow_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_stacked_solid_dark_holo.9.png b/core/res/res/drawable-xxhdpi/ab_stacked_solid_dark_holo.9.png
index 086069b..53992e8 100644
--- a/core/res/res/drawable-xxhdpi/ab_stacked_solid_dark_holo.9.png
+++ b/core/res/res/drawable-xxhdpi/ab_stacked_solid_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_stacked_solid_inverse_holo.9.png b/core/res/res/drawable-xxhdpi/ab_stacked_solid_inverse_holo.9.png
index 4074d81..7cd0c94 100644
--- a/core/res/res/drawable-xxhdpi/ab_stacked_solid_inverse_holo.9.png
+++ b/core/res/res/drawable-xxhdpi/ab_stacked_solid_inverse_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_stacked_solid_light_holo.9.png b/core/res/res/drawable-xxhdpi/ab_stacked_solid_light_holo.9.png
index 8ce58b3..967a41c 100644
--- a/core/res/res/drawable-xxhdpi/ab_stacked_solid_light_holo.9.png
+++ b/core/res/res/drawable-xxhdpi/ab_stacked_solid_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_stacked_transparent_dark_holo.9.png b/core/res/res/drawable-xxhdpi/ab_stacked_transparent_dark_holo.9.png
index fd92764..14c8817 100644
--- a/core/res/res/drawable-xxhdpi/ab_stacked_transparent_dark_holo.9.png
+++ b/core/res/res/drawable-xxhdpi/ab_stacked_transparent_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_stacked_transparent_light_holo.9.png b/core/res/res/drawable-xxhdpi/ab_stacked_transparent_light_holo.9.png
index 8d64aa7..cfff715 100644
--- a/core/res/res/drawable-xxhdpi/ab_stacked_transparent_light_holo.9.png
+++ b/core/res/res/drawable-xxhdpi/ab_stacked_transparent_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_transparent_dark_holo.9.png b/core/res/res/drawable-xxhdpi/ab_transparent_dark_holo.9.png
index 84155ccf..a33eedd 100644
--- a/core/res/res/drawable-xxhdpi/ab_transparent_dark_holo.9.png
+++ b/core/res/res/drawable-xxhdpi/ab_transparent_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_transparent_light_holo.9.png b/core/res/res/drawable-xxhdpi/ab_transparent_light_holo.9.png
index d48e27f..9ffa35f 100644
--- a/core/res/res/drawable-xxhdpi/ab_transparent_light_holo.9.png
+++ b/core/res/res/drawable-xxhdpi/ab_transparent_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_cab_done_default_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_cab_done_default_holo_dark.9.png
index 95475ee..b9fd9cb 100644
--- a/core/res/res/drawable-xxhdpi/btn_cab_done_default_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_cab_done_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_cab_done_default_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_cab_done_default_holo_light.9.png
index e1c55ad..1eb58ee 100644
--- a/core/res/res/drawable-xxhdpi/btn_cab_done_default_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_cab_done_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_cab_done_focused_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_cab_done_focused_holo_dark.9.png
index 6c49fe7..58bb4fb 100644
--- a/core/res/res/drawable-xxhdpi/btn_cab_done_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_cab_done_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_cab_done_focused_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_cab_done_focused_holo_light.9.png
index 35a557e..171cbc6 100644
--- a/core/res/res/drawable-xxhdpi/btn_cab_done_focused_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_cab_done_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_cab_done_pressed_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_cab_done_pressed_holo_dark.9.png
index 65f9009..07f74b3 100644
--- a/core/res/res/drawable-xxhdpi/btn_cab_done_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_cab_done_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_cab_done_pressed_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_cab_done_pressed_holo_light.9.png
index 1be216b..66b8fe7 100644
--- a/core/res/res/drawable-xxhdpi/btn_cab_done_pressed_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_cab_done_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_off_disabled_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_check_off_disabled_focused_holo_dark.png
index 0707776..606e060 100644
--- a/core/res/res/drawable-xxhdpi/btn_check_off_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_check_off_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_off_disabled_focused_holo_light.png b/core/res/res/drawable-xxhdpi/btn_check_off_disabled_focused_holo_light.png
index e1553b7..87e399c 100644
--- a/core/res/res/drawable-xxhdpi/btn_check_off_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_check_off_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_off_disabled_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_check_off_disabled_holo_dark.png
index e74b8b7..5bbcca9 100644
--- a/core/res/res/drawable-xxhdpi/btn_check_off_disabled_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_check_off_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_off_disabled_holo_light.png b/core/res/res/drawable-xxhdpi/btn_check_off_disabled_holo_light.png
index 47a6373..1112c54 100644
--- a/core/res/res/drawable-xxhdpi/btn_check_off_disabled_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_check_off_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_off_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_check_off_focused_holo_dark.png
index b0353feb..b16f744 100644
--- a/core/res/res/drawable-xxhdpi/btn_check_off_focused_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_check_off_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_off_focused_holo_light.png b/core/res/res/drawable-xxhdpi/btn_check_off_focused_holo_light.png
index 889a67c..2096ef5 100644
--- a/core/res/res/drawable-xxhdpi/btn_check_off_focused_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_check_off_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_off_holo.png b/core/res/res/drawable-xxhdpi/btn_check_off_holo.png
index cdcfdef..7bda6f9 100644
--- a/core/res/res/drawable-xxhdpi/btn_check_off_holo.png
+++ b/core/res/res/drawable-xxhdpi/btn_check_off_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_off_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_check_off_holo_dark.png
index ecfc08c..d90a20e3 100644
--- a/core/res/res/drawable-xxhdpi/btn_check_off_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_check_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_off_holo_light.png b/core/res/res/drawable-xxhdpi/btn_check_off_holo_light.png
index b067b58..6d8cfc8 100644
--- a/core/res/res/drawable-xxhdpi/btn_check_off_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_check_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_off_pressed_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_check_off_pressed_holo_dark.png
index 4c95f96..2009ea1 100644
--- a/core/res/res/drawable-xxhdpi/btn_check_off_pressed_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_check_off_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_off_pressed_holo_light.png b/core/res/res/drawable-xxhdpi/btn_check_off_pressed_holo_light.png
index df468e0..8866b73 100644
--- a/core/res/res/drawable-xxhdpi/btn_check_off_pressed_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_check_off_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_on_disabled_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_check_on_disabled_focused_holo_dark.png
index d249372..f1b04c1 100644
--- a/core/res/res/drawable-xxhdpi/btn_check_on_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_check_on_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_on_disabled_focused_holo_light.png b/core/res/res/drawable-xxhdpi/btn_check_on_disabled_focused_holo_light.png
index b544001..ef7a122 100644
--- a/core/res/res/drawable-xxhdpi/btn_check_on_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_check_on_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_on_disabled_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_check_on_disabled_holo_dark.png
index eff125b..8aab99e 100644
--- a/core/res/res/drawable-xxhdpi/btn_check_on_disabled_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_check_on_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_on_disabled_holo_light.png b/core/res/res/drawable-xxhdpi/btn_check_on_disabled_holo_light.png
index 013c1f6..26c06e99 100644
--- a/core/res/res/drawable-xxhdpi/btn_check_on_disabled_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_check_on_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_on_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_check_on_focused_holo_dark.png
index e0d942a..d709416 100644
--- a/core/res/res/drawable-xxhdpi/btn_check_on_focused_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_check_on_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_on_focused_holo_light.png b/core/res/res/drawable-xxhdpi/btn_check_on_focused_holo_light.png
index 83f8dfd..6e99a36 100644
--- a/core/res/res/drawable-xxhdpi/btn_check_on_focused_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_check_on_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_on_holo.png b/core/res/res/drawable-xxhdpi/btn_check_on_holo.png
index 6193147..2e82d129 100644
--- a/core/res/res/drawable-xxhdpi/btn_check_on_holo.png
+++ b/core/res/res/drawable-xxhdpi/btn_check_on_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_on_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_check_on_holo_dark.png
index 1aafc83..5a0a61b 100644
--- a/core/res/res/drawable-xxhdpi/btn_check_on_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_check_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_on_holo_light.png b/core/res/res/drawable-xxhdpi/btn_check_on_holo_light.png
index 11598dd..7e0a744 100644
--- a/core/res/res/drawable-xxhdpi/btn_check_on_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_check_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_on_pressed_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_check_on_pressed_holo_dark.png
index 668548b..bd1352e 100644
--- a/core/res/res/drawable-xxhdpi/btn_check_on_pressed_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_check_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_on_pressed_holo_light.png b/core/res/res/drawable-xxhdpi/btn_check_on_pressed_holo_light.png
index 385350c..bd2dc60 100644
--- a/core/res/res/drawable-xxhdpi/btn_check_on_pressed_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_check_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_default_disabled_focused_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_default_disabled_focused_holo_dark.9.png
index aea519c..e521cb8 100644
--- a/core/res/res/drawable-xxhdpi/btn_default_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_default_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_default_disabled_focused_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_default_disabled_focused_holo_light.9.png
index 8ec4bf5..e521cb8 100644
--- a/core/res/res/drawable-xxhdpi/btn_default_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_default_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_default_disabled_holo.9.png b/core/res/res/drawable-xxhdpi/btn_default_disabled_holo.9.png
index 60732b3..02e97cd 100644
--- a/core/res/res/drawable-xxhdpi/btn_default_disabled_holo.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_default_disabled_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_default_disabled_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_default_disabled_holo_dark.9.png
index 12bac53..310a993 100644
--- a/core/res/res/drawable-xxhdpi/btn_default_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_default_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_default_disabled_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_default_disabled_holo_light.9.png
index b4c90d4..310a993 100644
--- a/core/res/res/drawable-xxhdpi/btn_default_disabled_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_default_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_default_focused_holo.9.png b/core/res/res/drawable-xxhdpi/btn_default_focused_holo.9.png
index 33c3ebb..c49e541 100644
--- a/core/res/res/drawable-xxhdpi/btn_default_focused_holo.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_default_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_default_focused_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_default_focused_holo_dark.9.png
index f7bfd78..3419039 100644
--- a/core/res/res/drawable-xxhdpi/btn_default_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_default_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_default_focused_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_default_focused_holo_light.9.png
index 7f5432f..3419039 100644
--- a/core/res/res/drawable-xxhdpi/btn_default_focused_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_default_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_default_normal_holo.9.png b/core/res/res/drawable-xxhdpi/btn_default_normal_holo.9.png
index c1632c8..dcdb764 100644
--- a/core/res/res/drawable-xxhdpi/btn_default_normal_holo.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_default_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_default_normal_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_default_normal_holo_dark.9.png
index 6449593..ca9e521 100644
--- a/core/res/res/drawable-xxhdpi/btn_default_normal_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_default_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_default_normal_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_default_normal_holo_light.9.png
index 68be3c5..5841815 100644
--- a/core/res/res/drawable-xxhdpi/btn_default_normal_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_default_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_default_pressed_holo.9.png b/core/res/res/drawable-xxhdpi/btn_default_pressed_holo.9.png
index e05017c..a462106 100644
--- a/core/res/res/drawable-xxhdpi/btn_default_pressed_holo.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_default_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_default_pressed_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_default_pressed_holo_dark.9.png
index 016a5ee..08c0670 100644
--- a/core/res/res/drawable-xxhdpi/btn_default_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_default_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_default_pressed_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_default_pressed_holo_light.9.png
index 9521603..7ee00d6 100644
--- a/core/res/res/drawable-xxhdpi/btn_default_pressed_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_default_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_group_disabled_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_group_disabled_holo_dark.9.png
index 54ff2c0..198d6ea 100644
--- a/core/res/res/drawable-xxhdpi/btn_group_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_group_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_group_disabled_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_group_disabled_holo_light.9.png
index e3c4945..638200e 100644
--- a/core/res/res/drawable-xxhdpi/btn_group_disabled_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_group_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_group_focused_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_group_focused_holo_dark.9.png
index bd04226..f062e51 100644
--- a/core/res/res/drawable-xxhdpi/btn_group_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_group_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_group_focused_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_group_focused_holo_light.9.png
index f7aa79e..f062e51 100644
--- a/core/res/res/drawable-xxhdpi/btn_group_focused_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_group_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_group_normal_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_group_normal_holo_dark.9.png
index 26f98fc..54e3f73 100644
--- a/core/res/res/drawable-xxhdpi/btn_group_normal_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_group_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_group_normal_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_group_normal_holo_light.9.png
index 1ba39f2..e66a807 100644
--- a/core/res/res/drawable-xxhdpi/btn_group_normal_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_group_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_group_pressed_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_group_pressed_holo_dark.9.png
index 531acc4..2b6daf9 100644
--- a/core/res/res/drawable-xxhdpi/btn_group_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_group_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_group_pressed_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_group_pressed_holo_light.9.png
index 358f546..3cb3b07 100644
--- a/core/res/res/drawable-xxhdpi/btn_group_pressed_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_group_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_off_disabled_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_radio_off_disabled_focused_holo_dark.png
index 6c0f6f3..a3dea4d 100644
--- a/core/res/res/drawable-xxhdpi/btn_radio_off_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_radio_off_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_off_disabled_focused_holo_light.png b/core/res/res/drawable-xxhdpi/btn_radio_off_disabled_focused_holo_light.png
index 63ac52b..97d150c 100644
--- a/core/res/res/drawable-xxhdpi/btn_radio_off_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_radio_off_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_off_disabled_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_radio_off_disabled_holo_dark.png
index 946936e..f4c3aff 100644
--- a/core/res/res/drawable-xxhdpi/btn_radio_off_disabled_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_radio_off_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_off_disabled_holo_light.png b/core/res/res/drawable-xxhdpi/btn_radio_off_disabled_holo_light.png
index 06f0cc7..453a45c 100644
--- a/core/res/res/drawable-xxhdpi/btn_radio_off_disabled_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_radio_off_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_off_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_radio_off_focused_holo_dark.png
index abbf1ae..e02a97b 100644
--- a/core/res/res/drawable-xxhdpi/btn_radio_off_focused_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_radio_off_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_off_focused_holo_light.png b/core/res/res/drawable-xxhdpi/btn_radio_off_focused_holo_light.png
index 28f5843..b70bf7d 100644
--- a/core/res/res/drawable-xxhdpi/btn_radio_off_focused_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_radio_off_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_off_holo.png b/core/res/res/drawable-xxhdpi/btn_radio_off_holo.png
index c8ac939..04e2a37 100644
--- a/core/res/res/drawable-xxhdpi/btn_radio_off_holo.png
+++ b/core/res/res/drawable-xxhdpi/btn_radio_off_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_off_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_radio_off_holo_dark.png
index a7afd00..137d7c9 100644
--- a/core/res/res/drawable-xxhdpi/btn_radio_off_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_radio_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_off_holo_light.png b/core/res/res/drawable-xxhdpi/btn_radio_off_holo_light.png
index 43fac43..a31b0b3 100644
--- a/core/res/res/drawable-xxhdpi/btn_radio_off_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_radio_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_off_pressed_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_radio_off_pressed_holo_dark.png
index 39ff3d5..fd22030 100644
--- a/core/res/res/drawable-xxhdpi/btn_radio_off_pressed_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_radio_off_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_off_pressed_holo_light.png b/core/res/res/drawable-xxhdpi/btn_radio_off_pressed_holo_light.png
index 702155f..549778c 100644
--- a/core/res/res/drawable-xxhdpi/btn_radio_off_pressed_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_radio_off_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_on_disabled_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_radio_on_disabled_focused_holo_dark.png
index 16b2023..765a39c 100644
--- a/core/res/res/drawable-xxhdpi/btn_radio_on_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_radio_on_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_on_disabled_focused_holo_light.png b/core/res/res/drawable-xxhdpi/btn_radio_on_disabled_focused_holo_light.png
index f03d07f..5aae1205 100644
--- a/core/res/res/drawable-xxhdpi/btn_radio_on_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_radio_on_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_on_disabled_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_radio_on_disabled_holo_dark.png
index 66b833d..552dae3 100644
--- a/core/res/res/drawable-xxhdpi/btn_radio_on_disabled_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_radio_on_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_on_disabled_holo_light.png b/core/res/res/drawable-xxhdpi/btn_radio_on_disabled_holo_light.png
index adb7304..51e2a2c 100644
--- a/core/res/res/drawable-xxhdpi/btn_radio_on_disabled_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_radio_on_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_on_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_radio_on_focused_holo_dark.png
index cb7d6c8..c7c9062 100644
--- a/core/res/res/drawable-xxhdpi/btn_radio_on_focused_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_radio_on_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_on_focused_holo_light.png b/core/res/res/drawable-xxhdpi/btn_radio_on_focused_holo_light.png
index 12a0601..f81545b 100644
--- a/core/res/res/drawable-xxhdpi/btn_radio_on_focused_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_radio_on_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_on_holo.png b/core/res/res/drawable-xxhdpi/btn_radio_on_holo.png
index 2a11733..3f43fca 100644
--- a/core/res/res/drawable-xxhdpi/btn_radio_on_holo.png
+++ b/core/res/res/drawable-xxhdpi/btn_radio_on_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_on_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_radio_on_holo_dark.png
index f3ce811..c41b9ec 100644
--- a/core/res/res/drawable-xxhdpi/btn_radio_on_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_radio_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_on_holo_light.png b/core/res/res/drawable-xxhdpi/btn_radio_on_holo_light.png
index 43142b6..d134e80 100644
--- a/core/res/res/drawable-xxhdpi/btn_radio_on_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_radio_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_on_pressed_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_radio_on_pressed_holo_dark.png
index d43a0f9..3298f2c 100644
--- a/core/res/res/drawable-xxhdpi/btn_radio_on_pressed_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_radio_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_on_pressed_holo_light.png b/core/res/res/drawable-xxhdpi/btn_radio_on_pressed_holo_light.png
index c05643f..d04764f 100644
--- a/core/res/res/drawable-xxhdpi/btn_radio_on_pressed_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_radio_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_off_disabled_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_rating_star_off_disabled_focused_holo_dark.png
index 292c752..2b09048 100644
--- a/core/res/res/drawable-xxhdpi/btn_rating_star_off_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_off_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_off_disabled_focused_holo_light.png b/core/res/res/drawable-xxhdpi/btn_rating_star_off_disabled_focused_holo_light.png
index 635c009..f862ec4 100644
--- a/core/res/res/drawable-xxhdpi/btn_rating_star_off_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_off_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_off_disabled_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_rating_star_off_disabled_holo_dark.png
index fef0797..6979b1c 100644
--- a/core/res/res/drawable-xxhdpi/btn_rating_star_off_disabled_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_off_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_off_disabled_holo_light.png b/core/res/res/drawable-xxhdpi/btn_rating_star_off_disabled_holo_light.png
index c43977dd..f4f9d81 100644
--- a/core/res/res/drawable-xxhdpi/btn_rating_star_off_disabled_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_off_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_off_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_rating_star_off_focused_holo_dark.png
index 521dc80..bcfd69c 100644
--- a/core/res/res/drawable-xxhdpi/btn_rating_star_off_focused_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_off_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_off_focused_holo_light.png b/core/res/res/drawable-xxhdpi/btn_rating_star_off_focused_holo_light.png
index 71a367b..4484a36 100644
--- a/core/res/res/drawable-xxhdpi/btn_rating_star_off_focused_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_off_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_off_mtrl_alpha.png b/core/res/res/drawable-xxhdpi/btn_rating_star_off_mtrl_alpha.png
index 4b49faf..3632b44 100644
--- a/core/res/res/drawable-xxhdpi/btn_rating_star_off_mtrl_alpha.png
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_off_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_off_normal_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_rating_star_off_normal_holo_dark.png
index 35f72fa..7769a31 100644
--- a/core/res/res/drawable-xxhdpi/btn_rating_star_off_normal_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_off_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_off_normal_holo_light.png b/core/res/res/drawable-xxhdpi/btn_rating_star_off_normal_holo_light.png
index c8541c3..a980180 100644
--- a/core/res/res/drawable-xxhdpi/btn_rating_star_off_normal_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_off_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_off_pressed_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_rating_star_off_pressed_holo_dark.png
index 899e577..3beb09b 100644
--- a/core/res/res/drawable-xxhdpi/btn_rating_star_off_pressed_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_off_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_off_pressed_holo_light.png b/core/res/res/drawable-xxhdpi/btn_rating_star_off_pressed_holo_light.png
index aaa6826..92e9ecc 100644
--- a/core/res/res/drawable-xxhdpi/btn_rating_star_off_pressed_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_off_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_on_disabled_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_rating_star_on_disabled_focused_holo_dark.png
index e699edc..1943ee6 100644
--- a/core/res/res/drawable-xxhdpi/btn_rating_star_on_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_on_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_on_disabled_focused_holo_light.png b/core/res/res/drawable-xxhdpi/btn_rating_star_on_disabled_focused_holo_light.png
index a59c23c..2b3b583 100644
--- a/core/res/res/drawable-xxhdpi/btn_rating_star_on_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_on_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_on_disabled_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_rating_star_on_disabled_holo_dark.png
index d2504fb..5ada9d7 100644
--- a/core/res/res/drawable-xxhdpi/btn_rating_star_on_disabled_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_on_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_on_disabled_holo_light.png b/core/res/res/drawable-xxhdpi/btn_rating_star_on_disabled_holo_light.png
index d514bdd..dcc06e9 100644
--- a/core/res/res/drawable-xxhdpi/btn_rating_star_on_disabled_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_on_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_on_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_rating_star_on_focused_holo_dark.png
index 53c7a53..3aa1a8c 100644
--- a/core/res/res/drawable-xxhdpi/btn_rating_star_on_focused_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_on_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_on_focused_holo_light.png b/core/res/res/drawable-xxhdpi/btn_rating_star_on_focused_holo_light.png
index f942490..df19c9e 100644
--- a/core/res/res/drawable-xxhdpi/btn_rating_star_on_focused_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_on_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_on_mtrl_alpha.png b/core/res/res/drawable-xxhdpi/btn_rating_star_on_mtrl_alpha.png
index 561d9ef..3d38df1 100644
--- a/core/res/res/drawable-xxhdpi/btn_rating_star_on_mtrl_alpha.png
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_on_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_on_normal_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_rating_star_on_normal_holo_dark.png
index 11bae7c..a926512 100644
--- a/core/res/res/drawable-xxhdpi/btn_rating_star_on_normal_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_on_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_on_normal_holo_light.png b/core/res/res/drawable-xxhdpi/btn_rating_star_on_normal_holo_light.png
index 08804b5..1b8dc8c 100644
--- a/core/res/res/drawable-xxhdpi/btn_rating_star_on_normal_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_on_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_on_pressed_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_rating_star_on_pressed_holo_dark.png
index e15fc63..9ffc11b 100644
--- a/core/res/res/drawable-xxhdpi/btn_rating_star_on_pressed_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_on_pressed_holo_light.png b/core/res/res/drawable-xxhdpi/btn_rating_star_on_pressed_holo_light.png
index cc82a54..92fcb03 100644
--- a/core/res/res/drawable-xxhdpi/btn_rating_star_on_pressed_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_mtrl_alpha.png b/core/res/res/drawable-xxhdpi/btn_star_mtrl_alpha.png
index 7488ff9..90540cf 100644
--- a/core/res/res/drawable-xxhdpi/btn_star_mtrl_alpha.png
+++ b/core/res/res/drawable-xxhdpi/btn_star_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_off_disabled_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_star_off_disabled_focused_holo_dark.png
index 853243d..f7e07fb 100644
--- a/core/res/res/drawable-xxhdpi/btn_star_off_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_star_off_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_off_disabled_focused_holo_light.png b/core/res/res/drawable-xxhdpi/btn_star_off_disabled_focused_holo_light.png
index b5cd0bb..37f70ae 100644
--- a/core/res/res/drawable-xxhdpi/btn_star_off_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_star_off_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_off_disabled_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_star_off_disabled_holo_dark.png
index bb16a5f7..1dce503 100644
--- a/core/res/res/drawable-xxhdpi/btn_star_off_disabled_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_star_off_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_off_disabled_holo_light.png b/core/res/res/drawable-xxhdpi/btn_star_off_disabled_holo_light.png
index c178a9b..3f7941b 100644
--- a/core/res/res/drawable-xxhdpi/btn_star_off_disabled_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_star_off_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_off_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_star_off_focused_holo_dark.png
index 886f395..47b32d1 100644
--- a/core/res/res/drawable-xxhdpi/btn_star_off_focused_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_star_off_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_off_focused_holo_light.png b/core/res/res/drawable-xxhdpi/btn_star_off_focused_holo_light.png
index ab2b334..600375f 100644
--- a/core/res/res/drawable-xxhdpi/btn_star_off_focused_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_star_off_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_off_normal_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_star_off_normal_holo_dark.png
index 59a8547..b3eef48 100644
--- a/core/res/res/drawable-xxhdpi/btn_star_off_normal_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_star_off_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_off_normal_holo_light.png b/core/res/res/drawable-xxhdpi/btn_star_off_normal_holo_light.png
index 14cac81..ba7427e 100644
--- a/core/res/res/drawable-xxhdpi/btn_star_off_normal_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_star_off_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_off_pressed_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_star_off_pressed_holo_dark.png
index b756e79..c420645 100644
--- a/core/res/res/drawable-xxhdpi/btn_star_off_pressed_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_star_off_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_off_pressed_holo_light.png b/core/res/res/drawable-xxhdpi/btn_star_off_pressed_holo_light.png
index 89bf5b4..d2388f5 100644
--- a/core/res/res/drawable-xxhdpi/btn_star_off_pressed_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_star_off_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_on_disabled_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_star_on_disabled_focused_holo_dark.png
index 7027cc2..f732eaf 100644
--- a/core/res/res/drawable-xxhdpi/btn_star_on_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_star_on_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_on_disabled_focused_holo_light.png b/core/res/res/drawable-xxhdpi/btn_star_on_disabled_focused_holo_light.png
index d491c5b..5f133e4 100644
--- a/core/res/res/drawable-xxhdpi/btn_star_on_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_star_on_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_on_disabled_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_star_on_disabled_holo_dark.png
index f968b1a..1766325 100644
--- a/core/res/res/drawable-xxhdpi/btn_star_on_disabled_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_star_on_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_on_disabled_holo_light.png b/core/res/res/drawable-xxhdpi/btn_star_on_disabled_holo_light.png
index 1999f68..ac9273b 100644
--- a/core/res/res/drawable-xxhdpi/btn_star_on_disabled_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_star_on_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_on_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_star_on_focused_holo_dark.png
index ab4b58c..0d3a97e 100644
--- a/core/res/res/drawable-xxhdpi/btn_star_on_focused_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_star_on_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_on_focused_holo_light.png b/core/res/res/drawable-xxhdpi/btn_star_on_focused_holo_light.png
index cd44fa6..c5ddad9 100644
--- a/core/res/res/drawable-xxhdpi/btn_star_on_focused_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_star_on_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_on_normal_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_star_on_normal_holo_dark.png
index 8847d78..d4b1f12 100644
--- a/core/res/res/drawable-xxhdpi/btn_star_on_normal_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_star_on_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_on_normal_holo_light.png b/core/res/res/drawable-xxhdpi/btn_star_on_normal_holo_light.png
index 3ef0498..b5b1ed7 100644
--- a/core/res/res/drawable-xxhdpi/btn_star_on_normal_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_star_on_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_on_pressed_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_star_on_pressed_holo_dark.png
index 50e4940..e1bc8ef 100644
--- a/core/res/res/drawable-xxhdpi/btn_star_on_pressed_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_star_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_on_pressed_holo_light.png b/core/res/res/drawable-xxhdpi/btn_star_on_pressed_holo_light.png
index 0b77905..890f47c 100644
--- a/core/res/res/drawable-xxhdpi/btn_star_on_pressed_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/btn_star_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00001.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00001.9.png
index 1eca9a9..68de29e 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00001.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00002.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00002.9.png
index 5427211..f3d7590 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00002.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00003.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00003.9.png
index 43c06ab..b8526f5 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00003.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00004.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00004.9.png
index 6db3f1e..25ebc7f 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00004.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00005.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00005.9.png
index 53b3a62..a250068 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00005.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00006.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00006.9.png
index 7add520..d82a6b5 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00006.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00007.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00007.9.png
index a4d57de..a3f27f2 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00007.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00008.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00008.9.png
index 4b3a023..f852380 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00008.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00009.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00009.9.png
index a4caa65..730efc4 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00009.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00010.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00010.9.png
index 2ab46c0..49f4244 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00010.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00011.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00011.9.png
index 5c06e44..87d32ba 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00011.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00012.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00012.9.png
index 60d8c11..e7cef0b 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00012.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00001.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00001.9.png
index b149e47..83c1e1a 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00001.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00002.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00002.9.png
index 6a12a1f..d888179 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00002.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00003.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00003.9.png
index 2803c7c..20a6530 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00003.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00004.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00004.9.png
index 032f6ea..40f903e 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00004.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00005.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00005.9.png
index ea83c35..a92ab43 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00005.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00006.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00006.9.png
index 2801f29..e3c4765 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00006.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00007.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00007.9.png
index 66b89b3..a3f27f2 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00007.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00008.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00008.9.png
index 1f8770c..e7a633f 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00008.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00009.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00009.9.png
index 0d6a95b..5dc90bd 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00009.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00010.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00010.9.png
index 8e602db..4ceaf9b 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00010.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00011.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00011.9.png
index 3143c1f..7fb88bc 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00011.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00012.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00012.9.png
index 00fb83e..9079000 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00012.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_off_disabled_focused_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_off_disabled_focused_holo_dark.9.png
index e5ec283..6cdcc2e 100644
--- a/core/res/res/drawable-xxhdpi/btn_toggle_off_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_off_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_off_disabled_focused_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_off_disabled_focused_holo_light.9.png
index 5cd267d..6cdcc2e 100644
--- a/core/res/res/drawable-xxhdpi/btn_toggle_off_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_off_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_off_disabled_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_off_disabled_holo_dark.9.png
index c34c7af..1ae899e 100644
--- a/core/res/res/drawable-xxhdpi/btn_toggle_off_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_off_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_off_disabled_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_off_disabled_holo_light.9.png
index 9b3900a..1ae899e 100644
--- a/core/res/res/drawable-xxhdpi/btn_toggle_off_disabled_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_off_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_off_focused_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_off_focused_holo_dark.9.png
index 345fe9cd..56ec079 100644
--- a/core/res/res/drawable-xxhdpi/btn_toggle_off_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_off_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_off_focused_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_off_focused_holo_light.9.png
index b338843..56ec079 100644
--- a/core/res/res/drawable-xxhdpi/btn_toggle_off_focused_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_off_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_off_normal_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_off_normal_holo_dark.9.png
index 3f6ab80..15e0370 100644
--- a/core/res/res/drawable-xxhdpi/btn_toggle_off_normal_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_off_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_off_normal_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_off_normal_holo_light.9.png
index df71589..c4b9cd9 100644
--- a/core/res/res/drawable-xxhdpi/btn_toggle_off_normal_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_off_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_off_pressed_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_off_pressed_holo_dark.9.png
index 1e675d3..0da896b 100644
--- a/core/res/res/drawable-xxhdpi/btn_toggle_off_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_off_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_off_pressed_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_off_pressed_holo_light.9.png
index 2ceb802..98205ee 100644
--- a/core/res/res/drawable-xxhdpi/btn_toggle_off_pressed_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_off_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_on_disabled_focused_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_on_disabled_focused_holo_dark.9.png
index ea15883..bf2174e 100644
--- a/core/res/res/drawable-xxhdpi/btn_toggle_on_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_on_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_on_disabled_focused_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_on_disabled_focused_holo_light.9.png
index b403039..bf2174e 100644
--- a/core/res/res/drawable-xxhdpi/btn_toggle_on_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_on_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_on_disabled_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_on_disabled_holo_dark.9.png
index f12643e..8baac62 100644
--- a/core/res/res/drawable-xxhdpi/btn_toggle_on_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_on_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_on_disabled_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_on_disabled_holo_light.9.png
index 3090c9a..8baac62 100644
--- a/core/res/res/drawable-xxhdpi/btn_toggle_on_disabled_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_on_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_on_focused_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_on_focused_holo_dark.9.png
index 2fb4d91..4b50b4c 100644
--- a/core/res/res/drawable-xxhdpi/btn_toggle_on_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_on_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_on_focused_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_on_focused_holo_light.9.png
index 5e17dd5..4b50b4c 100644
--- a/core/res/res/drawable-xxhdpi/btn_toggle_on_focused_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_on_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_on_normal_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_on_normal_holo_dark.9.png
index bf9b997..d8d248c 100644
--- a/core/res/res/drawable-xxhdpi/btn_toggle_on_normal_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_on_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_on_normal_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_on_normal_holo_light.9.png
index b36f670c6..c8dcbe8 100644
--- a/core/res/res/drawable-xxhdpi/btn_toggle_on_normal_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_on_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_on_pressed_holo_dark.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_on_pressed_holo_dark.9.png
index e7a9265..e53ee25 100644
--- a/core/res/res/drawable-xxhdpi/btn_toggle_on_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_on_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_on_pressed_holo_light.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_on_pressed_holo_light.9.png
index df58767..e7c366b 100644
--- a/core/res/res/drawable-xxhdpi/btn_toggle_on_pressed_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_on_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/cab_background_bottom_holo_dark.9.png b/core/res/res/drawable-xxhdpi/cab_background_bottom_holo_dark.9.png
index 8666113..f4d09eb 100644
--- a/core/res/res/drawable-xxhdpi/cab_background_bottom_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/cab_background_bottom_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/cab_background_bottom_holo_light.9.png b/core/res/res/drawable-xxhdpi/cab_background_bottom_holo_light.9.png
index 805927b..d23236a 100644
--- a/core/res/res/drawable-xxhdpi/cab_background_bottom_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/cab_background_bottom_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/cab_background_bottom_mtrl_alpha.9.png b/core/res/res/drawable-xxhdpi/cab_background_bottom_mtrl_alpha.9.png
index 22bd8ce..8ab0b2d 100644
--- a/core/res/res/drawable-xxhdpi/cab_background_bottom_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xxhdpi/cab_background_bottom_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/cab_background_top_holo_dark.9.png b/core/res/res/drawable-xxhdpi/cab_background_top_holo_dark.9.png
index cbb4f4c..40e4aca 100644
--- a/core/res/res/drawable-xxhdpi/cab_background_top_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/cab_background_top_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/cab_background_top_holo_light.9.png b/core/res/res/drawable-xxhdpi/cab_background_top_holo_light.9.png
index 6d467f7..21c40fb 100644
--- a/core/res/res/drawable-xxhdpi/cab_background_top_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/cab_background_top_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/cab_background_top_mtrl_alpha.9.png b/core/res/res/drawable-xxhdpi/cab_background_top_mtrl_alpha.9.png
index 1dd64b9..f6d2f32 100644
--- a/core/res/res/drawable-xxhdpi/cab_background_top_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xxhdpi/cab_background_top_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/cling_arrow_up.png b/core/res/res/drawable-xxhdpi/cling_arrow_up.png
index 1983f13..9f0e447 100644
--- a/core/res/res/drawable-xxhdpi/cling_arrow_up.png
+++ b/core/res/res/drawable-xxhdpi/cling_arrow_up.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/cling_bg.9.png b/core/res/res/drawable-xxhdpi/cling_bg.9.png
index 7beae03..5da37c4 100644
--- a/core/res/res/drawable-xxhdpi/cling_bg.9.png
+++ b/core/res/res/drawable-xxhdpi/cling_bg.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/cling_button_normal.9.png b/core/res/res/drawable-xxhdpi/cling_button_normal.9.png
index e412876..7890ca5 100644
--- a/core/res/res/drawable-xxhdpi/cling_button_normal.9.png
+++ b/core/res/res/drawable-xxhdpi/cling_button_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/cling_button_pressed.9.png b/core/res/res/drawable-xxhdpi/cling_button_pressed.9.png
index 55e89da..d8e8f5c 100644
--- a/core/res/res/drawable-xxhdpi/cling_button_pressed.9.png
+++ b/core/res/res/drawable-xxhdpi/cling_button_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/combobox_disabled.png b/core/res/res/drawable-xxhdpi/combobox_disabled.png
index d342344..2fbbc39 100644
--- a/core/res/res/drawable-xxhdpi/combobox_disabled.png
+++ b/core/res/res/drawable-xxhdpi/combobox_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/combobox_nohighlight.png b/core/res/res/drawable-xxhdpi/combobox_nohighlight.png
index 377fbd3..ae4c855 100644
--- a/core/res/res/drawable-xxhdpi/combobox_nohighlight.png
+++ b/core/res/res/drawable-xxhdpi/combobox_nohighlight.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/create_contact.png b/core/res/res/drawable-xxhdpi/create_contact.png
index 9baf195..571d7482 100644
--- a/core/res/res/drawable-xxhdpi/create_contact.png
+++ b/core/res/res/drawable-xxhdpi/create_contact.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/day_picker_week_view_dayline_holo.9.png b/core/res/res/drawable-xxhdpi/day_picker_week_view_dayline_holo.9.png
index 6b22972..ec29667 100644
--- a/core/res/res/drawable-xxhdpi/day_picker_week_view_dayline_holo.9.png
+++ b/core/res/res/drawable-xxhdpi/day_picker_week_view_dayline_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/dialog_bottom_holo_dark.9.png b/core/res/res/drawable-xxhdpi/dialog_bottom_holo_dark.9.png
index 0d2ba50..acef1a2 100644
--- a/core/res/res/drawable-xxhdpi/dialog_bottom_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/dialog_bottom_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/dialog_bottom_holo_light.9.png b/core/res/res/drawable-xxhdpi/dialog_bottom_holo_light.9.png
index 13462d1..a495807 100644
--- a/core/res/res/drawable-xxhdpi/dialog_bottom_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/dialog_bottom_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/dialog_full_holo_dark.9.png b/core/res/res/drawable-xxhdpi/dialog_full_holo_dark.9.png
index b029809..d088b5a 100644
--- a/core/res/res/drawable-xxhdpi/dialog_full_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/dialog_full_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/dialog_full_holo_light.9.png b/core/res/res/drawable-xxhdpi/dialog_full_holo_light.9.png
index 63dd192..2bd46ad 100644
--- a/core/res/res/drawable-xxhdpi/dialog_full_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/dialog_full_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/dialog_ic_close_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/dialog_ic_close_focused_holo_dark.png
index ffe7cbf..bf59e33 100644
--- a/core/res/res/drawable-xxhdpi/dialog_ic_close_focused_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/dialog_ic_close_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/dialog_ic_close_focused_holo_light.png b/core/res/res/drawable-xxhdpi/dialog_ic_close_focused_holo_light.png
index f21e320..a0b5a62 100644
--- a/core/res/res/drawable-xxhdpi/dialog_ic_close_focused_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/dialog_ic_close_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/dialog_ic_close_normal_holo_dark.png b/core/res/res/drawable-xxhdpi/dialog_ic_close_normal_holo_dark.png
index 87cf4d5..fbb7dde 100644
--- a/core/res/res/drawable-xxhdpi/dialog_ic_close_normal_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/dialog_ic_close_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/dialog_ic_close_normal_holo_light.png b/core/res/res/drawable-xxhdpi/dialog_ic_close_normal_holo_light.png
index 8d185f4..9d5d056 100644
--- a/core/res/res/drawable-xxhdpi/dialog_ic_close_normal_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/dialog_ic_close_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/dialog_ic_close_pressed_holo_dark.png b/core/res/res/drawable-xxhdpi/dialog_ic_close_pressed_holo_dark.png
index cb2ec6a..ae3066d 100644
--- a/core/res/res/drawable-xxhdpi/dialog_ic_close_pressed_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/dialog_ic_close_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/dialog_ic_close_pressed_holo_light.png b/core/res/res/drawable-xxhdpi/dialog_ic_close_pressed_holo_light.png
index 776dbfd..004a080 100644
--- a/core/res/res/drawable-xxhdpi/dialog_ic_close_pressed_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/dialog_ic_close_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/dialog_middle_holo_dark.9.png b/core/res/res/drawable-xxhdpi/dialog_middle_holo_dark.9.png
index d922fd6..3624c20 100644
--- a/core/res/res/drawable-xxhdpi/dialog_middle_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/dialog_middle_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/dialog_middle_holo_light.9.png b/core/res/res/drawable-xxhdpi/dialog_middle_holo_light.9.png
index 1298194..d5ca283 100644
--- a/core/res/res/drawable-xxhdpi/dialog_middle_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/dialog_middle_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/dialog_top_holo_dark.9.png b/core/res/res/drawable-xxhdpi/dialog_top_holo_dark.9.png
index baf7be3..b004826 100644
--- a/core/res/res/drawable-xxhdpi/dialog_top_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/dialog_top_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/dialog_top_holo_light.9.png b/core/res/res/drawable-xxhdpi/dialog_top_holo_light.9.png
index f35251f..8dfe809 100644
--- a/core/res/res/drawable-xxhdpi/dialog_top_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/dialog_top_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/emo_im_angel.png b/core/res/res/drawable-xxhdpi/emo_im_angel.png
index 7d317e2..e16c5f5 100644
--- a/core/res/res/drawable-xxhdpi/emo_im_angel.png
+++ b/core/res/res/drawable-xxhdpi/emo_im_angel.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/emo_im_cool.png b/core/res/res/drawable-xxhdpi/emo_im_cool.png
index a05fabe..d93aea8 100644
--- a/core/res/res/drawable-xxhdpi/emo_im_cool.png
+++ b/core/res/res/drawable-xxhdpi/emo_im_cool.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/emo_im_crying.png b/core/res/res/drawable-xxhdpi/emo_im_crying.png
index 102800d..ef3bde5 100644
--- a/core/res/res/drawable-xxhdpi/emo_im_crying.png
+++ b/core/res/res/drawable-xxhdpi/emo_im_crying.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/emo_im_embarrassed.png b/core/res/res/drawable-xxhdpi/emo_im_embarrassed.png
index 6e5d226..44b3e08 100644
--- a/core/res/res/drawable-xxhdpi/emo_im_embarrassed.png
+++ b/core/res/res/drawable-xxhdpi/emo_im_embarrassed.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/emo_im_foot_in_mouth.png b/core/res/res/drawable-xxhdpi/emo_im_foot_in_mouth.png
index c328f8c..e687ad9 100644
--- a/core/res/res/drawable-xxhdpi/emo_im_foot_in_mouth.png
+++ b/core/res/res/drawable-xxhdpi/emo_im_foot_in_mouth.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/emo_im_happy.png b/core/res/res/drawable-xxhdpi/emo_im_happy.png
index 11e0163..1a46665 100644
--- a/core/res/res/drawable-xxhdpi/emo_im_happy.png
+++ b/core/res/res/drawable-xxhdpi/emo_im_happy.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/emo_im_kissing.png b/core/res/res/drawable-xxhdpi/emo_im_kissing.png
index b929861..4dc80dd 100644
--- a/core/res/res/drawable-xxhdpi/emo_im_kissing.png
+++ b/core/res/res/drawable-xxhdpi/emo_im_kissing.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/emo_im_laughing.png b/core/res/res/drawable-xxhdpi/emo_im_laughing.png
index 4ed90bc..fabb0b5 100644
--- a/core/res/res/drawable-xxhdpi/emo_im_laughing.png
+++ b/core/res/res/drawable-xxhdpi/emo_im_laughing.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/emo_im_lips_are_sealed.png b/core/res/res/drawable-xxhdpi/emo_im_lips_are_sealed.png
index bcbcf8d..4a1eb8b 100644
--- a/core/res/res/drawable-xxhdpi/emo_im_lips_are_sealed.png
+++ b/core/res/res/drawable-xxhdpi/emo_im_lips_are_sealed.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/emo_im_money_mouth.png b/core/res/res/drawable-xxhdpi/emo_im_money_mouth.png
index e17cf77..b8233b3 100644
--- a/core/res/res/drawable-xxhdpi/emo_im_money_mouth.png
+++ b/core/res/res/drawable-xxhdpi/emo_im_money_mouth.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/emo_im_sad.png b/core/res/res/drawable-xxhdpi/emo_im_sad.png
index 0696d99..1bfbb46 100644
--- a/core/res/res/drawable-xxhdpi/emo_im_sad.png
+++ b/core/res/res/drawable-xxhdpi/emo_im_sad.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/emo_im_surprised.png b/core/res/res/drawable-xxhdpi/emo_im_surprised.png
index bd821d7..95c904c 100644
--- a/core/res/res/drawable-xxhdpi/emo_im_surprised.png
+++ b/core/res/res/drawable-xxhdpi/emo_im_surprised.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/emo_im_tongue_sticking_out.png b/core/res/res/drawable-xxhdpi/emo_im_tongue_sticking_out.png
index af21474..52d0a7b 100644
--- a/core/res/res/drawable-xxhdpi/emo_im_tongue_sticking_out.png
+++ b/core/res/res/drawable-xxhdpi/emo_im_tongue_sticking_out.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/emo_im_undecided.png b/core/res/res/drawable-xxhdpi/emo_im_undecided.png
index c43aa0b..e1c45bd 100644
--- a/core/res/res/drawable-xxhdpi/emo_im_undecided.png
+++ b/core/res/res/drawable-xxhdpi/emo_im_undecided.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/emo_im_winking.png b/core/res/res/drawable-xxhdpi/emo_im_winking.png
index 41cdd23..210f82d 100644
--- a/core/res/res/drawable-xxhdpi/emo_im_winking.png
+++ b/core/res/res/drawable-xxhdpi/emo_im_winking.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/emo_im_wtf.png b/core/res/res/drawable-xxhdpi/emo_im_wtf.png
index 36f0b32..fa4c7d3 100644
--- a/core/res/res/drawable-xxhdpi/emo_im_wtf.png
+++ b/core/res/res/drawable-xxhdpi/emo_im_wtf.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/emo_im_yelling.png b/core/res/res/drawable-xxhdpi/emo_im_yelling.png
index db210eb..47fe299 100644
--- a/core/res/res/drawable-xxhdpi/emo_im_yelling.png
+++ b/core/res/res/drawable-xxhdpi/emo_im_yelling.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/expander_close_holo_dark.9.png b/core/res/res/drawable-xxhdpi/expander_close_holo_dark.9.png
index fb41e44a..d47d06c 100644
--- a/core/res/res/drawable-xxhdpi/expander_close_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/expander_close_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/expander_close_holo_light.9.png b/core/res/res/drawable-xxhdpi/expander_close_holo_light.9.png
index f3042a7..627a60a 100644
--- a/core/res/res/drawable-xxhdpi/expander_close_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/expander_close_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/expander_close_mtrl_alpha.9.png b/core/res/res/drawable-xxhdpi/expander_close_mtrl_alpha.9.png
index e78fff6..c7a0f6b 100644
--- a/core/res/res/drawable-xxhdpi/expander_close_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xxhdpi/expander_close_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/expander_open_holo_dark.9.png b/core/res/res/drawable-xxhdpi/expander_open_holo_dark.9.png
index b1f006a..ff64ab0 100644
--- a/core/res/res/drawable-xxhdpi/expander_open_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/expander_open_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/expander_open_holo_light.9.png b/core/res/res/drawable-xxhdpi/expander_open_holo_light.9.png
index bac07f6..d4394c1 100644
--- a/core/res/res/drawable-xxhdpi/expander_open_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/expander_open_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/expander_open_mtrl_alpha.9.png b/core/res/res/drawable-xxhdpi/expander_open_mtrl_alpha.9.png
index a3d09657..d095593 100644
--- a/core/res/res/drawable-xxhdpi/expander_open_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xxhdpi/expander_open_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/fastscroll_label_left_holo_dark.9.png b/core/res/res/drawable-xxhdpi/fastscroll_label_left_holo_dark.9.png
index c9b5893..fce5f4e 100644
--- a/core/res/res/drawable-xxhdpi/fastscroll_label_left_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/fastscroll_label_left_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/fastscroll_label_left_holo_light.9.png b/core/res/res/drawable-xxhdpi/fastscroll_label_left_holo_light.9.png
index a1326ed..ee3607b 100644
--- a/core/res/res/drawable-xxhdpi/fastscroll_label_left_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/fastscroll_label_left_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/fastscroll_label_right_holo_dark.9.png b/core/res/res/drawable-xxhdpi/fastscroll_label_right_holo_dark.9.png
index 91152ea..b3341f5 100644
--- a/core/res/res/drawable-xxhdpi/fastscroll_label_right_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/fastscroll_label_right_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/fastscroll_label_right_holo_light.9.png b/core/res/res/drawable-xxhdpi/fastscroll_label_right_holo_light.9.png
index 1541e97..8e88111 100644
--- a/core/res/res/drawable-xxhdpi/fastscroll_label_right_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/fastscroll_label_right_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/fastscroll_thumb_default_holo.png b/core/res/res/drawable-xxhdpi/fastscroll_thumb_default_holo.png
index d8335d5..af251a2 100644
--- a/core/res/res/drawable-xxhdpi/fastscroll_thumb_default_holo.png
+++ b/core/res/res/drawable-xxhdpi/fastscroll_thumb_default_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/fastscroll_thumb_pressed_holo.png b/core/res/res/drawable-xxhdpi/fastscroll_thumb_pressed_holo.png
index cdc13e1..559e0a9 100644
--- a/core/res/res/drawable-xxhdpi/fastscroll_thumb_pressed_holo.png
+++ b/core/res/res/drawable-xxhdpi/fastscroll_thumb_pressed_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/fastscroll_track_default_holo_dark.9.png b/core/res/res/drawable-xxhdpi/fastscroll_track_default_holo_dark.9.png
index b9455ff..32bc27d 100644
--- a/core/res/res/drawable-xxhdpi/fastscroll_track_default_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/fastscroll_track_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/fastscroll_track_default_holo_light.9.png b/core/res/res/drawable-xxhdpi/fastscroll_track_default_holo_light.9.png
index a5c54dc..32bc27d 100644
--- a/core/res/res/drawable-xxhdpi/fastscroll_track_default_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/fastscroll_track_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/fastscroll_track_pressed_holo_dark.9.png b/core/res/res/drawable-xxhdpi/fastscroll_track_pressed_holo_dark.9.png
index eaf0969..f949ecc 100644
--- a/core/res/res/drawable-xxhdpi/fastscroll_track_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/fastscroll_track_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/fastscroll_track_pressed_holo_light.9.png b/core/res/res/drawable-xxhdpi/fastscroll_track_pressed_holo_light.9.png
index 9db45c0..f8a3d4f 100644
--- a/core/res/res/drawable-xxhdpi/fastscroll_track_pressed_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/fastscroll_track_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_ab_back_holo_dark_am.png b/core/res/res/drawable-xxhdpi/ic_ab_back_holo_dark_am.png
index 04d1348..b75cc9f 100644
--- a/core/res/res/drawable-xxhdpi/ic_ab_back_holo_dark_am.png
+++ b/core/res/res/drawable-xxhdpi/ic_ab_back_holo_dark_am.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_ab_back_holo_light_am.png b/core/res/res/drawable-xxhdpi/ic_ab_back_holo_light_am.png
index 962dba3..00abd27 100644
--- a/core/res/res/drawable-xxhdpi/ic_ab_back_holo_light_am.png
+++ b/core/res/res/drawable-xxhdpi/ic_ab_back_holo_light_am.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_notification_am_alpha.png b/core/res/res/drawable-xxhdpi/ic_audio_notification_am_alpha.png
index fb0e96e..34850d5 100644
--- a/core/res/res/drawable-xxhdpi/ic_audio_notification_am_alpha.png
+++ b/core/res/res/drawable-xxhdpi/ic_audio_notification_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_notification_mute_am_alpha.png b/core/res/res/drawable-xxhdpi/ic_audio_notification_mute_am_alpha.png
index 3aa7b53..f4cde1a 100644
--- a/core/res/res/drawable-xxhdpi/ic_audio_notification_mute_am_alpha.png
+++ b/core/res/res/drawable-xxhdpi/ic_audio_notification_mute_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_btn_search_go.png b/core/res/res/drawable-xxhdpi/ic_btn_search_go.png
index 1f4301d..b06c750 100644
--- a/core/res/res/drawable-xxhdpi/ic_btn_search_go.png
+++ b/core/res/res/drawable-xxhdpi/ic_btn_search_go.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_btn_speak_now.png b/core/res/res/drawable-xxhdpi/ic_btn_speak_now.png
index b15f385..23202fe 100644
--- a/core/res/res/drawable-xxhdpi/ic_btn_speak_now.png
+++ b/core/res/res/drawable-xxhdpi/ic_btn_speak_now.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_bullet_key_permission.png b/core/res/res/drawable-xxhdpi/ic_bullet_key_permission.png
index a74c286..127ecbd 100644
--- a/core/res/res/drawable-xxhdpi/ic_bullet_key_permission.png
+++ b/core/res/res/drawable-xxhdpi/ic_bullet_key_permission.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_cab_done_holo.png b/core/res/res/drawable-xxhdpi/ic_cab_done_holo.png
index a23a3ae..de7f325 100644
--- a/core/res/res/drawable-xxhdpi/ic_cab_done_holo.png
+++ b/core/res/res/drawable-xxhdpi/ic_cab_done_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_cab_done_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_cab_done_holo_dark.png
index fdecbe1..f8b3481 100644
--- a/core/res/res/drawable-xxhdpi/ic_cab_done_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/ic_cab_done_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_cab_done_holo_light.png b/core/res/res/drawable-xxhdpi/ic_cab_done_holo_light.png
index ca93e70..dde8776 100644
--- a/core/res/res/drawable-xxhdpi/ic_cab_done_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/ic_cab_done_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_cab_done_mtrl_alpha.png b/core/res/res/drawable-xxhdpi/ic_cab_done_mtrl_alpha.png
index 1f9c734..36ac61c 100644
--- a/core/res/res/drawable-xxhdpi/ic_cab_done_mtrl_alpha.png
+++ b/core/res/res/drawable-xxhdpi/ic_cab_done_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_commit_search_api_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_commit_search_api_holo_dark.png
index 6e48dc6..f9a6b40 100644
--- a/core/res/res/drawable-xxhdpi/ic_commit_search_api_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/ic_commit_search_api_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_commit_search_api_holo_light.png b/core/res/res/drawable-xxhdpi/ic_commit_search_api_holo_light.png
index d26f75e..d22c74c 100644
--- a/core/res/res/drawable-xxhdpi/ic_commit_search_api_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/ic_commit_search_api_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_commit_search_api_mtrl_alpha.png b/core/res/res/drawable-xxhdpi/ic_commit_search_api_mtrl_alpha.png
index fc1b8b4..df4a30e 100644
--- a/core/res/res/drawable-xxhdpi/ic_commit_search_api_mtrl_alpha.png
+++ b/core/res/res/drawable-xxhdpi/ic_commit_search_api_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_contact_picture.png b/core/res/res/drawable-xxhdpi/ic_contact_picture.png
index b36ec17..56ef2d6 100644
--- a/core/res/res/drawable-xxhdpi/ic_contact_picture.png
+++ b/core/res/res/drawable-xxhdpi/ic_contact_picture.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_contact_picture_180_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_contact_picture_180_holo_dark.png
index 6e057ac..48708440 100644
--- a/core/res/res/drawable-xxhdpi/ic_contact_picture_180_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/ic_contact_picture_180_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_contact_picture_180_holo_light.png b/core/res/res/drawable-xxhdpi/ic_contact_picture_180_holo_light.png
index 4111bc5..69fb91d 100644
--- a/core/res/res/drawable-xxhdpi/ic_contact_picture_180_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/ic_contact_picture_180_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_contact_picture_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_contact_picture_holo_dark.png
index 52a69c3..365b35c 100644
--- a/core/res/res/drawable-xxhdpi/ic_contact_picture_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/ic_contact_picture_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_contact_picture_holo_light.png b/core/res/res/drawable-xxhdpi/ic_contact_picture_holo_light.png
index 5a41c23..6ca617a 100644
--- a/core/res/res/drawable-xxhdpi/ic_contact_picture_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/ic_contact_picture_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_dialog_alert_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_dialog_alert_holo_dark.png
index cdd6fd8..3a87322 100644
--- a/core/res/res/drawable-xxhdpi/ic_dialog_alert_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/ic_dialog_alert_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_dialog_alert_holo_light.png b/core/res/res/drawable-xxhdpi/ic_dialog_alert_holo_light.png
index 24ec28c..64c7616 100644
--- a/core/res/res/drawable-xxhdpi/ic_dialog_alert_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/ic_dialog_alert_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_emergency.png b/core/res/res/drawable-xxhdpi/ic_emergency.png
index d070311d..69129c1 100644
--- a/core/res/res/drawable-xxhdpi/ic_emergency.png
+++ b/core/res/res/drawable-xxhdpi/ic_emergency.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_find_next_mtrl_alpha.png b/core/res/res/drawable-xxhdpi/ic_find_next_mtrl_alpha.png
index e3a7e9e..a435ea6 100644
--- a/core/res/res/drawable-xxhdpi/ic_find_next_mtrl_alpha.png
+++ b/core/res/res/drawable-xxhdpi/ic_find_next_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_find_previous_mtrl_alpha.png b/core/res/res/drawable-xxhdpi/ic_find_previous_mtrl_alpha.png
index f9cf16c..2a78590 100644
--- a/core/res/res/drawable-xxhdpi/ic_find_previous_mtrl_alpha.png
+++ b/core/res/res/drawable-xxhdpi/ic_find_previous_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_input_delete.png b/core/res/res/drawable-xxhdpi/ic_input_delete.png
index ea047dd..218ad0d 100644
--- a/core/res/res/drawable-xxhdpi/ic_input_delete.png
+++ b/core/res/res/drawable-xxhdpi/ic_input_delete.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_launcher_android.png b/core/res/res/drawable-xxhdpi/ic_launcher_android.png
index 81268b3..a0e5a14 100644
--- a/core/res/res/drawable-xxhdpi/ic_launcher_android.png
+++ b/core/res/res/drawable-xxhdpi/ic_launcher_android.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lock_airplane_mode_alpha.png b/core/res/res/drawable-xxhdpi/ic_lock_airplane_mode_alpha.png
index 116b891..db22099 100644
--- a/core/res/res/drawable-xxhdpi/ic_lock_airplane_mode_alpha.png
+++ b/core/res/res/drawable-xxhdpi/ic_lock_airplane_mode_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lock_airplane_mode_off_am_alpha.png b/core/res/res/drawable-xxhdpi/ic_lock_airplane_mode_off_am_alpha.png
index 5ca72ed..74bb643 100644
--- a/core/res/res/drawable-xxhdpi/ic_lock_airplane_mode_off_am_alpha.png
+++ b/core/res/res/drawable-xxhdpi/ic_lock_airplane_mode_off_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lock_idle_alarm_alpha.png b/core/res/res/drawable-xxhdpi/ic_lock_idle_alarm_alpha.png
index ed2d3c5..c5c3b8f 100644
--- a/core/res/res/drawable-xxhdpi/ic_lock_idle_alarm_alpha.png
+++ b/core/res/res/drawable-xxhdpi/ic_lock_idle_alarm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lock_lock_alpha.png b/core/res/res/drawable-xxhdpi/ic_lock_lock_alpha.png
index 1b8882c..a30a26b 100644
--- a/core/res/res/drawable-xxhdpi/ic_lock_lock_alpha.png
+++ b/core/res/res/drawable-xxhdpi/ic_lock_lock_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lock_open_wht_24dp.png b/core/res/res/drawable-xxhdpi/ic_lock_open_wht_24dp.png
index 1b11b59..e4a1340 100644
--- a/core/res/res/drawable-xxhdpi/ic_lock_open_wht_24dp.png
+++ b/core/res/res/drawable-xxhdpi/ic_lock_open_wht_24dp.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lock_outline_wht_24dp.png b/core/res/res/drawable-xxhdpi/ic_lock_outline_wht_24dp.png
index ae0d655..f251c1c 100644
--- a/core/res/res/drawable-xxhdpi/ic_lock_outline_wht_24dp.png
+++ b/core/res/res/drawable-xxhdpi/ic_lock_outline_wht_24dp.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lock_power_off_alpha.png b/core/res/res/drawable-xxhdpi/ic_lock_power_off_alpha.png
index 061dc78..18a90b9e 100644
--- a/core/res/res/drawable-xxhdpi/ic_lock_power_off_alpha.png
+++ b/core/res/res/drawable-xxhdpi/ic_lock_power_off_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lock_silent_mode_off.png b/core/res/res/drawable-xxhdpi/ic_lock_silent_mode_off.png
index 2cca958..3df95af 100644
--- a/core/res/res/drawable-xxhdpi/ic_lock_silent_mode_off.png
+++ b/core/res/res/drawable-xxhdpi/ic_lock_silent_mode_off.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_alarm.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_alarm.png
index f53fa8f..14bcba2 100644
--- a/core/res/res/drawable-xxhdpi/ic_lockscreen_alarm.png
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_alarm.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_answer_active.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_answer_active.png
index 78a560f..69899fd 100644
--- a/core/res/res/drawable-xxhdpi/ic_lockscreen_answer_active.png
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_answer_active.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_answer_focused.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_answer_focused.png
index 9c21761..772d1ef 100644
--- a/core/res/res/drawable-xxhdpi/ic_lockscreen_answer_focused.png
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_answer_focused.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_answer_normal.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_answer_normal.png
index 9298b61..e8f0286 100644
--- a/core/res/res/drawable-xxhdpi/ic_lockscreen_answer_normal.png
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_answer_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_camera_activated.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_camera_activated.png
index c41fe84..a1f7f43 100644
--- a/core/res/res/drawable-xxhdpi/ic_lockscreen_camera_activated.png
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_camera_activated.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_camera_normal.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_camera_normal.png
index 3c29157..baa7664 100644
--- a/core/res/res/drawable-xxhdpi/ic_lockscreen_camera_normal.png
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_camera_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_chevron_down.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_chevron_down.png
index 8b3458b..87ec069 100644
--- a/core/res/res/drawable-xxhdpi/ic_lockscreen_chevron_down.png
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_chevron_down.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_chevron_left.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_chevron_left.png
index 10cad65..f649690 100644
--- a/core/res/res/drawable-xxhdpi/ic_lockscreen_chevron_left.png
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_chevron_left.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_chevron_right.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_chevron_right.png
index 9fe0601..50a3069 100644
--- a/core/res/res/drawable-xxhdpi/ic_lockscreen_chevron_right.png
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_chevron_right.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_chevron_up.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_chevron_up.png
index 8e9d6d0..2085afa 100644
--- a/core/res/res/drawable-xxhdpi/ic_lockscreen_chevron_up.png
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_chevron_up.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_decline_activated.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_decline_activated.png
index 1d114b1..43c1c72 100644
--- a/core/res/res/drawable-xxhdpi/ic_lockscreen_decline_activated.png
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_decline_activated.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_decline_focused.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_decline_focused.png
index 4db7876..cf005dc 100644
--- a/core/res/res/drawable-xxhdpi/ic_lockscreen_decline_focused.png
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_decline_focused.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_decline_normal.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_decline_normal.png
index 89aece4..d541a43 100644
--- a/core/res/res/drawable-xxhdpi/ic_lockscreen_decline_normal.png
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_decline_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_emergencycall_normal.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_emergencycall_normal.png
index 4b99bad..6cfdbc9 100644
--- a/core/res/res/drawable-xxhdpi/ic_lockscreen_emergencycall_normal.png
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_emergencycall_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_emergencycall_pressed.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_emergencycall_pressed.png
index d1bd72e..9b0b97e 100644
--- a/core/res/res/drawable-xxhdpi/ic_lockscreen_emergencycall_pressed.png
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_emergencycall_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_forgotpassword_normal.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_forgotpassword_normal.png
index ece563c..f2b1886 100644
--- a/core/res/res/drawable-xxhdpi/ic_lockscreen_forgotpassword_normal.png
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_forgotpassword_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_forgotpassword_pressed.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_forgotpassword_pressed.png
index ff3dfa1..a6ec85e 100644
--- a/core/res/res/drawable-xxhdpi/ic_lockscreen_forgotpassword_pressed.png
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_forgotpassword_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_google_activated.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_google_activated.png
index d03fc06..dc8e0f6 100644
--- a/core/res/res/drawable-xxhdpi/ic_lockscreen_google_activated.png
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_google_activated.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_google_focused.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_google_focused.png
index 76124a9..0cd012e 100644
--- a/core/res/res/drawable-xxhdpi/ic_lockscreen_google_focused.png
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_google_focused.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_google_normal.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_google_normal.png
index d0680dc..f017e46 100644
--- a/core/res/res/drawable-xxhdpi/ic_lockscreen_google_normal.png
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_google_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_handle_normal.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_handle_normal.png
index a5418d8..c7a48e6 100644
--- a/core/res/res/drawable-xxhdpi/ic_lockscreen_handle_normal.png
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_handle_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_handle_pressed.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_handle_pressed.png
index 7528064..cad224b 100644
--- a/core/res/res/drawable-xxhdpi/ic_lockscreen_handle_pressed.png
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_handle_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_player_background.9.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_player_background.9.png
index 6dacccf..65d1eea 100644
--- a/core/res/res/drawable-xxhdpi/ic_lockscreen_player_background.9.png
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_player_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_puk.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_puk.png
index 61db8cd..12d9af39 100644
--- a/core/res/res/drawable-xxhdpi/ic_lockscreen_puk.png
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_puk.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_silent_activated.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_silent_activated.png
index fd295ec..b6f96d7 100644
--- a/core/res/res/drawable-xxhdpi/ic_lockscreen_silent_activated.png
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_silent_activated.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_silent_focused.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_silent_focused.png
index a2e1b69..03b16ab 100644
--- a/core/res/res/drawable-xxhdpi/ic_lockscreen_silent_focused.png
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_silent_focused.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_silent_normal.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_silent_normal.png
index d791ffa..2b20286 100644
--- a/core/res/res/drawable-xxhdpi/ic_lockscreen_silent_normal.png
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_silent_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_sim.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_sim.png
index 3ba4331a..ec9fdda 100644
--- a/core/res/res/drawable-xxhdpi/ic_lockscreen_sim.png
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_sim.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_soundon_activated.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_soundon_activated.png
index e469bf4..0ee7850 100644
--- a/core/res/res/drawable-xxhdpi/ic_lockscreen_soundon_activated.png
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_soundon_activated.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_soundon_focused.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_soundon_focused.png
index 89b3213..1d89ca2 100644
--- a/core/res/res/drawable-xxhdpi/ic_lockscreen_soundon_focused.png
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_soundon_focused.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_soundon_normal.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_soundon_normal.png
index 72bc5ee..200d12b 100644
--- a/core/res/res/drawable-xxhdpi/ic_lockscreen_soundon_normal.png
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_soundon_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_text_activated.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_text_activated.png
index 10cbb7e..7f138f7 100644
--- a/core/res/res/drawable-xxhdpi/ic_lockscreen_text_activated.png
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_text_activated.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_text_focusde.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_text_focusde.png
index 0cf7307..12371b31 100644
--- a/core/res/res/drawable-xxhdpi/ic_lockscreen_text_focusde.png
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_text_focusde.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_text_normal.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_text_normal.png
index 304996d..e39c5fa 100644
--- a/core/res/res/drawable-xxhdpi/ic_lockscreen_text_normal.png
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_text_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_unlock_activated.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_unlock_activated.png
index dbd5d48..4b2786c 100644
--- a/core/res/res/drawable-xxhdpi/ic_lockscreen_unlock_activated.png
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_unlock_activated.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreen_unlock_normal.png b/core/res/res/drawable-xxhdpi/ic_lockscreen_unlock_normal.png
index 153bfa9..f4f7f03 100644
--- a/core/res/res/drawable-xxhdpi/ic_lockscreen_unlock_normal.png
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreen_unlock_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lockscreens_now_button.png b/core/res/res/drawable-xxhdpi/ic_lockscreens_now_button.png
index 74ad3c8..f7864c7 100644
--- a/core/res/res/drawable-xxhdpi/ic_lockscreens_now_button.png
+++ b/core/res/res/drawable-xxhdpi/ic_lockscreens_now_button.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_embed_play.png b/core/res/res/drawable-xxhdpi/ic_media_embed_play.png
index 3bf5a82..e514fad 100644
--- a/core/res/res/drawable-xxhdpi/ic_media_embed_play.png
+++ b/core/res/res/drawable-xxhdpi/ic_media_embed_play.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_ff.png b/core/res/res/drawable-xxhdpi/ic_media_ff.png
index ab9e022..780e11b 100644
--- a/core/res/res/drawable-xxhdpi/ic_media_ff.png
+++ b/core/res/res/drawable-xxhdpi/ic_media_ff.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_fullscreen.png b/core/res/res/drawable-xxhdpi/ic_media_fullscreen.png
index 5734f16..a1f19b0 100644
--- a/core/res/res/drawable-xxhdpi/ic_media_fullscreen.png
+++ b/core/res/res/drawable-xxhdpi/ic_media_fullscreen.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_next.png b/core/res/res/drawable-xxhdpi/ic_media_next.png
index ce0a143..30bd2de 100644
--- a/core/res/res/drawable-xxhdpi/ic_media_next.png
+++ b/core/res/res/drawable-xxhdpi/ic_media_next.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_pause.png b/core/res/res/drawable-xxhdpi/ic_media_pause.png
index 9a36b17..ddaf9ef 100644
--- a/core/res/res/drawable-xxhdpi/ic_media_pause.png
+++ b/core/res/res/drawable-xxhdpi/ic_media_pause.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_play.png b/core/res/res/drawable-xxhdpi/ic_media_play.png
index 41f76bb..f70d4eb 100644
--- a/core/res/res/drawable-xxhdpi/ic_media_play.png
+++ b/core/res/res/drawable-xxhdpi/ic_media_play.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_previous.png b/core/res/res/drawable-xxhdpi/ic_media_previous.png
index d468874..8b3e638 100644
--- a/core/res/res/drawable-xxhdpi/ic_media_previous.png
+++ b/core/res/res/drawable-xxhdpi/ic_media_previous.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_rew.png b/core/res/res/drawable-xxhdpi/ic_media_rew.png
index 8ebb2cc..f4208da 100644
--- a/core/res/res/drawable-xxhdpi/ic_media_rew.png
+++ b/core/res/res/drawable-xxhdpi/ic_media_rew.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_disabled_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_media_route_disabled_holo_dark.png
index 6fad4a64..99654c98 100644
--- a/core/res/res/drawable-xxhdpi/ic_media_route_disabled_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_disabled_holo_light.png b/core/res/res/drawable-xxhdpi/ic_media_route_disabled_holo_light.png
index 865617c..7005e95 100644
--- a/core/res/res/drawable-xxhdpi/ic_media_route_disabled_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_disabled_mtrl_alpha.png b/core/res/res/drawable-xxhdpi/ic_media_route_disabled_mtrl_alpha.png
index 6fad4a64..99654c98 100644
--- a/core/res/res/drawable-xxhdpi/ic_media_route_disabled_mtrl_alpha.png
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_disabled_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_off_dark_mtrl.png b/core/res/res/drawable-xxhdpi/ic_media_route_off_dark_mtrl.png
index 9acbd29..23d5863 100644
--- a/core/res/res/drawable-xxhdpi/ic_media_route_off_dark_mtrl.png
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_off_dark_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_off_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_media_route_off_holo_dark.png
index 44d98d5..1093529 100644
--- a/core/res/res/drawable-xxhdpi/ic_media_route_off_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_off_holo_light.png b/core/res/res/drawable-xxhdpi/ic_media_route_off_holo_light.png
index b5b29b0..b0693eb 100644
--- a/core/res/res/drawable-xxhdpi/ic_media_route_off_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_off_light_mtrl.png b/core/res/res/drawable-xxhdpi/ic_media_route_off_light_mtrl.png
index 5d4273d..6b7a2e7 100644
--- a/core/res/res/drawable-xxhdpi/ic_media_route_off_light_mtrl.png
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_off_light_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_0_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_0_holo_dark.png
index c807b50..fc6066a 100644
--- a/core/res/res/drawable-xxhdpi/ic_media_route_on_0_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_0_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_0_holo_light.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_0_holo_light.png
index 3fc7188..3ef4de1 100644
--- a/core/res/res/drawable-xxhdpi/ic_media_route_on_0_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_0_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_1_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_1_holo_dark.png
index d54f44a..2a6e1d7 100644
--- a/core/res/res/drawable-xxhdpi/ic_media_route_on_1_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_1_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_1_holo_light.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_1_holo_light.png
index 092fe8c..8ec1321 100644
--- a/core/res/res/drawable-xxhdpi/ic_media_route_on_1_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_1_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_2_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_2_holo_dark.png
index 17c1d99..10979ee 100644
--- a/core/res/res/drawable-xxhdpi/ic_media_route_on_2_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_2_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_2_holo_light.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_2_holo_light.png
index 4fd5808..341c754 100644
--- a/core/res/res/drawable-xxhdpi/ic_media_route_on_2_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_2_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_holo_dark.png
index 906401e..1f2426a 100644
--- a/core/res/res/drawable-xxhdpi/ic_media_route_on_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_holo_light.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_holo_light.png
index d29e563..87f0036 100644
--- a/core/res/res/drawable-xxhdpi/ic_media_route_on_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_stop.png b/core/res/res/drawable-xxhdpi/ic_media_stop.png
index c09989a..4243d34 100644
--- a/core/res/res/drawable-xxhdpi/ic_media_stop.png
+++ b/core/res/res/drawable-xxhdpi/ic_media_stop.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_account_list.png b/core/res/res/drawable-xxhdpi/ic_menu_account_list.png
index e072523..b8b7834 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_account_list.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_account_list.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_add.png b/core/res/res/drawable-xxhdpi/ic_menu_add.png
index 18a83a1..78f6b64c 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_add.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_add.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_agenda.png b/core/res/res/drawable-xxhdpi/ic_menu_agenda.png
index 20f350b..706b684 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_agenda.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_agenda.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_allfriends.png b/core/res/res/drawable-xxhdpi/ic_menu_allfriends.png
index c07a7c7..f5cd560 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_allfriends.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_allfriends.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_always_landscape_portrait.png b/core/res/res/drawable-xxhdpi/ic_menu_always_landscape_portrait.png
index 2decf65..c1a2469 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_always_landscape_portrait.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_always_landscape_portrait.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_archive.png b/core/res/res/drawable-xxhdpi/ic_menu_archive.png
index a2d93b9..6c7d112 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_archive.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_archive.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_attachment.png b/core/res/res/drawable-xxhdpi/ic_menu_attachment.png
index a92f66b..dffe286 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_attachment.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_attachment.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_back.png b/core/res/res/drawable-xxhdpi/ic_menu_back.png
index d3191ca..8b28514 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_back.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_back.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_block.png b/core/res/res/drawable-xxhdpi/ic_menu_block.png
index 6b8f78d..c32a5f9 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_block.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_block.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_blocked_user.png b/core/res/res/drawable-xxhdpi/ic_menu_blocked_user.png
index 096bfe4..d611dc5 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_blocked_user.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_blocked_user.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_btn_add.png b/core/res/res/drawable-xxhdpi/ic_menu_btn_add.png
index 18a83a1..78f6b64c 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_btn_add.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_btn_add.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_call.png b/core/res/res/drawable-xxhdpi/ic_menu_call.png
index 3b99ebb..9caa9a0 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_call.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_call.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_camera.png b/core/res/res/drawable-xxhdpi/ic_menu_camera.png
index e09d050..65a4690 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_camera.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_camera.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_cc_am.png b/core/res/res/drawable-xxhdpi/ic_menu_cc_am.png
index 5f1b341..f4acb18 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_cc_am.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_cc_am.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_chat_dashboard.png b/core/res/res/drawable-xxhdpi/ic_menu_chat_dashboard.png
index 92fdd99..cf16301 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_chat_dashboard.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_chat_dashboard.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_clear_playlist.png b/core/res/res/drawable-xxhdpi/ic_menu_clear_playlist.png
index 819e839..434a235 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_clear_playlist.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_clear_playlist.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_compass.png b/core/res/res/drawable-xxhdpi/ic_menu_compass.png
index 068678d..56d9c0b 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_compass.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_compass.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_compose.png b/core/res/res/drawable-xxhdpi/ic_menu_compose.png
index f4ccc2d..89d62f5 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_compose.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_compose.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_copy.png b/core/res/res/drawable-xxhdpi/ic_menu_copy.png
index 222e083..e94bdb0 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_copy.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_copy.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_copy_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_menu_copy_holo_dark.png
index 9dd56ef..40e2ccd 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_copy_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_copy_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_copy_holo_light.png b/core/res/res/drawable-xxhdpi/ic_menu_copy_holo_light.png
index 91043c9..1cdaf85 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_copy_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_copy_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_crop.png b/core/res/res/drawable-xxhdpi/ic_menu_crop.png
index 4cc11ca..2c1e270 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_crop.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_crop.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_cut.png b/core/res/res/drawable-xxhdpi/ic_menu_cut.png
index 81f45c6..3cf7360 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_cut.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_cut.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_cut_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_menu_cut_holo_dark.png
index 1bec21c..c30f111 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_cut_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_cut_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_cut_holo_light.png b/core/res/res/drawable-xxhdpi/ic_menu_cut_holo_light.png
index 0dfab90..495713d 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_cut_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_cut_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_day.png b/core/res/res/drawable-xxhdpi/ic_menu_day.png
index 6b92894..e1cd77d 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_day.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_day.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_delete.png b/core/res/res/drawable-xxhdpi/ic_menu_delete.png
index 8e9e78d4..7f3d517 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_delete.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_delete.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_directions.png b/core/res/res/drawable-xxhdpi/ic_menu_directions.png
index f8a50c5..efd811e 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_directions.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_directions.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_edit.png b/core/res/res/drawable-xxhdpi/ic_menu_edit.png
index 2b6e967..7cbfe17 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_edit.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_edit.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_emoticons.png b/core/res/res/drawable-xxhdpi/ic_menu_emoticons.png
index eae564f..ba8e0ee 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_emoticons.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_emoticons.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_end_conversation.png b/core/res/res/drawable-xxhdpi/ic_menu_end_conversation.png
index dd94956..28aef3d 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_end_conversation.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_end_conversation.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_find.png b/core/res/res/drawable-xxhdpi/ic_menu_find.png
index 32fad0a..917e2ab 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_find.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_find.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_find_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_menu_find_holo_dark.png
index f15e47a..c228e0b 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_find_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_find_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_find_holo_light.png b/core/res/res/drawable-xxhdpi/ic_menu_find_holo_light.png
index 61f6128..b4dac29 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_find_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_find_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_find_mtrl_alpha.png b/core/res/res/drawable-xxhdpi/ic_menu_find_mtrl_alpha.png
index d35b337..bd5b5d1 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_find_mtrl_alpha.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_find_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_forward.png b/core/res/res/drawable-xxhdpi/ic_menu_forward.png
index ca7eff9..f9285cf 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_forward.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_forward.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_friendslist.png b/core/res/res/drawable-xxhdpi/ic_menu_friendslist.png
index 920d687..049304f 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_friendslist.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_friendslist.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_gallery.png b/core/res/res/drawable-xxhdpi/ic_menu_gallery.png
index 3140ba9..5b8c40e 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_gallery.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_gallery.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_goto.png b/core/res/res/drawable-xxhdpi/ic_menu_goto.png
index 0d2109c..b8c8f63 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_goto.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_goto.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_help.png b/core/res/res/drawable-xxhdpi/ic_menu_help.png
index a16ad70..0ed1019 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_help.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_help.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_help_holo_light.png b/core/res/res/drawable-xxhdpi/ic_menu_help_holo_light.png
index 62c9eda..5556575 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_help_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_help_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_home.png b/core/res/res/drawable-xxhdpi/ic_menu_home.png
index 23c67d0..5a0c33c 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_home.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_home.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_info_details.png b/core/res/res/drawable-xxhdpi/ic_menu_info_details.png
index 4414bea..b4b7072 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_info_details.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_info_details.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_invite.png b/core/res/res/drawable-xxhdpi/ic_menu_invite.png
index 8020fd8..188b9e2 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_invite.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_invite.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_login.png b/core/res/res/drawable-xxhdpi/ic_menu_login.png
index 2ac01e9..4beeb98 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_login.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_login.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_manage.png b/core/res/res/drawable-xxhdpi/ic_menu_manage.png
index 733b759..06945d2 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_manage.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_manage.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_mapmode.png b/core/res/res/drawable-xxhdpi/ic_menu_mapmode.png
index 4d8c185..7e535e5 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_mapmode.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_mapmode.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_mark.png b/core/res/res/drawable-xxhdpi/ic_menu_mark.png
index 768aeb3..46cc3a0 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_mark.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_mark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_month.png b/core/res/res/drawable-xxhdpi/ic_menu_month.png
index b591a23..dc31b4d 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_month.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_month.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_more.png b/core/res/res/drawable-xxhdpi/ic_menu_more.png
index 7e0bb5e..8fa1d64 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_more.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_more.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow.png b/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow.png
index c3a1390..d575628 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow_focused_holo_dark.png
index 9cddee4..afac041 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow_focused_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow_focused_holo_light.png b/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow_focused_holo_light.png
index 826e724..f52ecac 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow_focused_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow_normal_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow_normal_holo_dark.png
index 498a9ff..c7a2eab 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow_normal_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow_normal_holo_light.png b/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow_normal_holo_light.png
index d3d3f1a..47b7de1 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow_normal_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_my_calendar.png b/core/res/res/drawable-xxhdpi/ic_menu_my_calendar.png
index a9285fe..75e56f3 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_my_calendar.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_my_calendar.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_mylocation.png b/core/res/res/drawable-xxhdpi/ic_menu_mylocation.png
index 8ea61e1..d5f11ec 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_mylocation.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_mylocation.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_myplaces.png b/core/res/res/drawable-xxhdpi/ic_menu_myplaces.png
index 85b3f20..5a813cd 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_myplaces.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_myplaces.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_notifications.png b/core/res/res/drawable-xxhdpi/ic_menu_notifications.png
index d72a365..2e4182e 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_notifications.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_notifications.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_paste.png b/core/res/res/drawable-xxhdpi/ic_menu_paste.png
index 11f560c..4dd2c68 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_paste.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_paste.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_paste_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_menu_paste_holo_dark.png
index d0b1fdb..1d9f3e4 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_paste_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_paste_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_paste_holo_light.png b/core/res/res/drawable-xxhdpi/ic_menu_paste_holo_light.png
index 27d01a69..6f7aeed 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_paste_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_paste_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_play_clip.png b/core/res/res/drawable-xxhdpi/ic_menu_play_clip.png
index 5c3b1e3..9197e09 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_play_clip.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_play_clip.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_preferences.png b/core/res/res/drawable-xxhdpi/ic_menu_preferences.png
index b039537..50f0605 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_preferences.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_preferences.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_recent_history.png b/core/res/res/drawable-xxhdpi/ic_menu_recent_history.png
index a3640a6..c654cad 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_recent_history.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_recent_history.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_report_image.png b/core/res/res/drawable-xxhdpi/ic_menu_report_image.png
index b8cf01e..18fdd38 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_report_image.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_report_image.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_revert.png b/core/res/res/drawable-xxhdpi/ic_menu_revert.png
index 009cb91..c0a3532 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_revert.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_revert.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_rotate.png b/core/res/res/drawable-xxhdpi/ic_menu_rotate.png
index fd6781f..42a2301 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_rotate.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_rotate.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_save.png b/core/res/res/drawable-xxhdpi/ic_menu_save.png
index 800da9a..0590e76 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_save.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_save.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_search.png b/core/res/res/drawable-xxhdpi/ic_menu_search.png
index 22bb4c8..4cbc5cb 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_search.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_search.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_search_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_menu_search_holo_dark.png
index 4ba4314..d1086ae 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_search_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_search_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_search_holo_light.png b/core/res/res/drawable-xxhdpi/ic_menu_search_holo_light.png
index c69d526..0939b31 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_search_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_search_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_search_mtrl_alpha.png b/core/res/res/drawable-xxhdpi/ic_menu_search_mtrl_alpha.png
index 6f60bd3..cc34455 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_search_mtrl_alpha.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_search_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_selectall_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_menu_selectall_holo_dark.png
index 9608411..e9fb96f 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_selectall_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_selectall_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_selectall_holo_light.png b/core/res/res/drawable-xxhdpi/ic_menu_selectall_holo_light.png
index f66ab27..624b1f9 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_selectall_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_selectall_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_send.png b/core/res/res/drawable-xxhdpi/ic_menu_send.png
index 7674d24..9338ed6 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_send.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_send.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_set_as.png b/core/res/res/drawable-xxhdpi/ic_menu_set_as.png
index 667d723..9cd9214 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_set_as.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_set_as.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_settings_holo_light.png b/core/res/res/drawable-xxhdpi/ic_menu_settings_holo_light.png
index 5df7a55..4111319e 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_settings_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_settings_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_share.png b/core/res/res/drawable-xxhdpi/ic_menu_share.png
index 7b90639..4c6fcd1 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_share.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_share.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_share_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_menu_share_holo_dark.png
index cc0cdda..19e709e 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_share_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_share_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_share_holo_light.png b/core/res/res/drawable-xxhdpi/ic_menu_share_holo_light.png
index 1e21d9d..b996c2e6 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_share_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_share_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_slideshow.png b/core/res/res/drawable-xxhdpi/ic_menu_slideshow.png
index 5db7bc7..2c5c584 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_slideshow.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_slideshow.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_sort_alphabetically.png b/core/res/res/drawable-xxhdpi/ic_menu_sort_alphabetically.png
index bb925f2..c9500bc 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_sort_alphabetically.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_sort_alphabetically.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_sort_by_size.png b/core/res/res/drawable-xxhdpi/ic_menu_sort_by_size.png
index da3b4a7..fb5c213 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_sort_by_size.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_sort_by_size.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_star.png b/core/res/res/drawable-xxhdpi/ic_menu_star.png
index 63ce68d..12df65f 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_star.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_star.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_start_conversation.png b/core/res/res/drawable-xxhdpi/ic_menu_start_conversation.png
index bb26e49..546d5ed 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_start_conversation.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_start_conversation.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_stop.png b/core/res/res/drawable-xxhdpi/ic_menu_stop.png
index 992738d..9e96cac 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_stop.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_stop.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_today.png b/core/res/res/drawable-xxhdpi/ic_menu_today.png
index b5d58d80..dc2dc13 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_today.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_today.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_upload.png b/core/res/res/drawable-xxhdpi/ic_menu_upload.png
index 931e6ed..5079efa 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_upload.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_upload.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_upload_you_tube.png b/core/res/res/drawable-xxhdpi/ic_menu_upload_you_tube.png
index fd8f409..6086dfe 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_upload_you_tube.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_upload_you_tube.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_view.png b/core/res/res/drawable-xxhdpi/ic_menu_view.png
index aff6c86..5d8c284 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_view.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_view.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_week.png b/core/res/res/drawable-xxhdpi/ic_menu_week.png
index 8da6b1e..01baae5 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_week.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_week.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_zoom.png b/core/res/res/drawable-xxhdpi/ic_menu_zoom.png
index f6a5c30..51574d6 100644
--- a/core/res/res/drawable-xxhdpi/ic_menu_zoom.png
+++ b/core/res/res/drawable-xxhdpi/ic_menu_zoom.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_notification_cast_0.png b/core/res/res/drawable-xxhdpi/ic_notification_cast_0.png
index 7ef0d3d..29cfdac 100644
--- a/core/res/res/drawable-xxhdpi/ic_notification_cast_0.png
+++ b/core/res/res/drawable-xxhdpi/ic_notification_cast_0.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_notification_cast_1.png b/core/res/res/drawable-xxhdpi/ic_notification_cast_1.png
index ed04beb..f7cbf0e 100644
--- a/core/res/res/drawable-xxhdpi/ic_notification_cast_1.png
+++ b/core/res/res/drawable-xxhdpi/ic_notification_cast_1.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_notification_cast_2.png b/core/res/res/drawable-xxhdpi/ic_notification_cast_2.png
index d62d27d..bef49e7 100644
--- a/core/res/res/drawable-xxhdpi/ic_notification_cast_2.png
+++ b/core/res/res/drawable-xxhdpi/ic_notification_cast_2.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_notification_media_route.png b/core/res/res/drawable-xxhdpi/ic_notification_media_route.png
index da1a627..87563f3 100644
--- a/core/res/res/drawable-xxhdpi/ic_notification_media_route.png
+++ b/core/res/res/drawable-xxhdpi/ic_notification_media_route.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_app_info.png b/core/res/res/drawable-xxhdpi/ic_perm_group_app_info.png
index 11f2638..7ae05a8 100644
--- a/core/res/res/drawable-xxhdpi/ic_perm_group_app_info.png
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_app_info.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_audio_settings.png b/core/res/res/drawable-xxhdpi/ic_perm_group_audio_settings.png
index aaf8f76..f150794 100644
--- a/core/res/res/drawable-xxhdpi/ic_perm_group_audio_settings.png
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_audio_settings.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_bluetooth.png b/core/res/res/drawable-xxhdpi/ic_perm_group_bluetooth.png
index b302cc7..0d5142f7 100644
--- a/core/res/res/drawable-xxhdpi/ic_perm_group_bluetooth.png
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_bluetooth.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_bookmarks.png b/core/res/res/drawable-xxhdpi/ic_perm_group_bookmarks.png
index 75aee05..e197f98 100644
--- a/core/res/res/drawable-xxhdpi/ic_perm_group_bookmarks.png
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_bookmarks.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_calendar.png b/core/res/res/drawable-xxhdpi/ic_perm_group_calendar.png
index ad3629c..95fd0f3 100644
--- a/core/res/res/drawable-xxhdpi/ic_perm_group_calendar.png
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_calendar.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_camera.png b/core/res/res/drawable-xxhdpi/ic_perm_group_camera.png
index e22ffb8..c1267d3 100644
--- a/core/res/res/drawable-xxhdpi/ic_perm_group_camera.png
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_camera.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_device_alarms.png b/core/res/res/drawable-xxhdpi/ic_perm_group_device_alarms.png
index 0b48a24..0220bce 100644
--- a/core/res/res/drawable-xxhdpi/ic_perm_group_device_alarms.png
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_device_alarms.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_display.png b/core/res/res/drawable-xxhdpi/ic_perm_group_display.png
index 29e6332..d3b270c 100644
--- a/core/res/res/drawable-xxhdpi/ic_perm_group_display.png
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_display.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_effects_battery.png b/core/res/res/drawable-xxhdpi/ic_perm_group_effects_battery.png
index afe137a..d4f1e85 100644
--- a/core/res/res/drawable-xxhdpi/ic_perm_group_effects_battery.png
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_effects_battery.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_location.png b/core/res/res/drawable-xxhdpi/ic_perm_group_location.png
index 7124634..3759b35 100644
--- a/core/res/res/drawable-xxhdpi/ic_perm_group_location.png
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_location.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_messages.png b/core/res/res/drawable-xxhdpi/ic_perm_group_messages.png
index 9534dcb..d76536b 100644
--- a/core/res/res/drawable-xxhdpi/ic_perm_group_messages.png
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_messages.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_microphone.png b/core/res/res/drawable-xxhdpi/ic_perm_group_microphone.png
index 723a2cf..26eb6bd 100644
--- a/core/res/res/drawable-xxhdpi/ic_perm_group_microphone.png
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_microphone.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_network.png b/core/res/res/drawable-xxhdpi/ic_perm_group_network.png
index 703b25b..473eceb 100644
--- a/core/res/res/drawable-xxhdpi/ic_perm_group_network.png
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_network.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_personal_info.png b/core/res/res/drawable-xxhdpi/ic_perm_group_personal_info.png
index 2428976..2298580 100644
--- a/core/res/res/drawable-xxhdpi/ic_perm_group_personal_info.png
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_personal_info.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_phone_calls.png b/core/res/res/drawable-xxhdpi/ic_perm_group_phone_calls.png
index 67e523c..0cf057e 100644
--- a/core/res/res/drawable-xxhdpi/ic_perm_group_phone_calls.png
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_phone_calls.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_screenlock.png b/core/res/res/drawable-xxhdpi/ic_perm_group_screenlock.png
index d660740..17b4b4e 100644
--- a/core/res/res/drawable-xxhdpi/ic_perm_group_screenlock.png
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_screenlock.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_shortrange_network.png b/core/res/res/drawable-xxhdpi/ic_perm_group_shortrange_network.png
index 3aae345..9e02ec7 100644
--- a/core/res/res/drawable-xxhdpi/ic_perm_group_shortrange_network.png
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_shortrange_network.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_social_info.png b/core/res/res/drawable-xxhdpi/ic_perm_group_social_info.png
index a3d7b26..bf6ff8a 100644
--- a/core/res/res/drawable-xxhdpi/ic_perm_group_social_info.png
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_social_info.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_status_bar.png b/core/res/res/drawable-xxhdpi/ic_perm_group_status_bar.png
index e260acf..227b695 100644
--- a/core/res/res/drawable-xxhdpi/ic_perm_group_status_bar.png
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_status_bar.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_sync_settings.png b/core/res/res/drawable-xxhdpi/ic_perm_group_sync_settings.png
index 41ef06b..af95b3e 100644
--- a/core/res/res/drawable-xxhdpi/ic_perm_group_sync_settings.png
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_sync_settings.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_system_clock.png b/core/res/res/drawable-xxhdpi/ic_perm_group_system_clock.png
index 5a89628..e2b1284 100644
--- a/core/res/res/drawable-xxhdpi/ic_perm_group_system_clock.png
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_system_clock.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_system_tools.png b/core/res/res/drawable-xxhdpi/ic_perm_group_system_tools.png
index cee2b05..d4d72a1 100644
--- a/core/res/res/drawable-xxhdpi/ic_perm_group_system_tools.png
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_system_tools.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_voicemail.png b/core/res/res/drawable-xxhdpi/ic_perm_group_voicemail.png
index 118c140..e7ecda5 100644
--- a/core/res/res/drawable-xxhdpi/ic_perm_group_voicemail.png
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_voicemail.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_wallpapewr.png b/core/res/res/drawable-xxhdpi/ic_perm_group_wallpapewr.png
index f95cd9d..0b66d09 100644
--- a/core/res/res/drawable-xxhdpi/ic_perm_group_wallpapewr.png
+++ b/core/res/res/drawable-xxhdpi/ic_perm_group_wallpapewr.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_search_api_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_search_api_holo_dark.png
index eb30465..c16e27d 100644
--- a/core/res/res/drawable-xxhdpi/ic_search_api_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/ic_search_api_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_search_api_holo_light.png b/core/res/res/drawable-xxhdpi/ic_search_api_holo_light.png
index bc14415..8a6291d 100644
--- a/core/res/res/drawable-xxhdpi/ic_search_api_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/ic_search_api_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_settings.png b/core/res/res/drawable-xxhdpi/ic_settings.png
index 452942e..c5efeea 100644
--- a/core/res/res/drawable-xxhdpi/ic_settings.png
+++ b/core/res/res/drawable-xxhdpi/ic_settings.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_sim_card_multi_24px_clr.png b/core/res/res/drawable-xxhdpi/ic_sim_card_multi_24px_clr.png
index db26fbf..db1d12a 100644
--- a/core/res/res/drawable-xxhdpi/ic_sim_card_multi_24px_clr.png
+++ b/core/res/res/drawable-xxhdpi/ic_sim_card_multi_24px_clr.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_sim_card_multi_48px_clr.png b/core/res/res/drawable-xxhdpi/ic_sim_card_multi_48px_clr.png
index dddb0a1..b0baf35 100644
--- a/core/res/res/drawable-xxhdpi/ic_sim_card_multi_48px_clr.png
+++ b/core/res/res/drawable-xxhdpi/ic_sim_card_multi_48px_clr.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_star_half_black_16dp.png b/core/res/res/drawable-xxhdpi/ic_star_half_black_16dp.png
index 9b268d1..8e79e1c 100644
--- a/core/res/res/drawable-xxhdpi/ic_star_half_black_16dp.png
+++ b/core/res/res/drawable-xxhdpi/ic_star_half_black_16dp.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_star_half_black_36dp.png b/core/res/res/drawable-xxhdpi/ic_star_half_black_36dp.png
index 167d8ae..3634612 100644
--- a/core/res/res/drawable-xxhdpi/ic_star_half_black_36dp.png
+++ b/core/res/res/drawable-xxhdpi/ic_star_half_black_36dp.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_star_half_black_48dp.png b/core/res/res/drawable-xxhdpi/ic_star_half_black_48dp.png
index 64e76bb..fa5b801 100644
--- a/core/res/res/drawable-xxhdpi/ic_star_half_black_48dp.png
+++ b/core/res/res/drawable-xxhdpi/ic_star_half_black_48dp.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_suggestions_add.png b/core/res/res/drawable-xxhdpi/ic_suggestions_add.png
index b880d40..2b3edbb 100644
--- a/core/res/res/drawable-xxhdpi/ic_suggestions_add.png
+++ b/core/res/res/drawable-xxhdpi/ic_suggestions_add.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_suggestions_delete.png b/core/res/res/drawable-xxhdpi/ic_suggestions_delete.png
index f9e2702..76d3b37 100644
--- a/core/res/res/drawable-xxhdpi/ic_suggestions_delete.png
+++ b/core/res/res/drawable-xxhdpi/ic_suggestions_delete.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_voice_search_api_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_voice_search_api_holo_dark.png
index 813048c..5ba570e 100644
--- a/core/res/res/drawable-xxhdpi/ic_voice_search_api_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/ic_voice_search_api_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_voice_search_api_holo_light.png b/core/res/res/drawable-xxhdpi/ic_voice_search_api_holo_light.png
index 8addde0..6415b37 100644
--- a/core/res/res/drawable-xxhdpi/ic_voice_search_api_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/ic_voice_search_api_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/indicator_input_error.png b/core/res/res/drawable-xxhdpi/indicator_input_error.png
index b5a6eaf..1316445 100644
--- a/core/res/res/drawable-xxhdpi/indicator_input_error.png
+++ b/core/res/res/drawable-xxhdpi/indicator_input_error.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/list_activated_holo.9.png b/core/res/res/drawable-xxhdpi/list_activated_holo.9.png
index 9f08bb0..23a33e4 100644
--- a/core/res/res/drawable-xxhdpi/list_activated_holo.9.png
+++ b/core/res/res/drawable-xxhdpi/list_activated_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/list_divider_holo_dark.9.png b/core/res/res/drawable-xxhdpi/list_divider_holo_dark.9.png
index 9678825..af46699 100644
--- a/core/res/res/drawable-xxhdpi/list_divider_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/list_divider_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/list_divider_holo_light.9.png b/core/res/res/drawable-xxhdpi/list_divider_holo_light.9.png
index c69a6a3..94d65b2 100644
--- a/core/res/res/drawable-xxhdpi/list_divider_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/list_divider_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/list_focused_holo.9.png b/core/res/res/drawable-xxhdpi/list_focused_holo.9.png
index 76cad17..290b5d4 100644
--- a/core/res/res/drawable-xxhdpi/list_focused_holo.9.png
+++ b/core/res/res/drawable-xxhdpi/list_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/list_longpressed_holo.9.png b/core/res/res/drawable-xxhdpi/list_longpressed_holo.9.png
index 8f436ea..23a33e4 100644
--- a/core/res/res/drawable-xxhdpi/list_longpressed_holo.9.png
+++ b/core/res/res/drawable-xxhdpi/list_longpressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/list_longpressed_holo_dark.9.png b/core/res/res/drawable-xxhdpi/list_longpressed_holo_dark.9.png
index 6eb451fcc..015265d 100644
--- a/core/res/res/drawable-xxhdpi/list_longpressed_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/list_longpressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/list_longpressed_holo_light.9.png b/core/res/res/drawable-xxhdpi/list_longpressed_holo_light.9.png
index 230d649..b56d595 100644
--- a/core/res/res/drawable-xxhdpi/list_longpressed_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/list_longpressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/list_pressed_holo_dark.9.png b/core/res/res/drawable-xxhdpi/list_pressed_holo_dark.9.png
index d4952ea..0c0789a 100644
--- a/core/res/res/drawable-xxhdpi/list_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/list_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/list_pressed_holo_light.9.png b/core/res/res/drawable-xxhdpi/list_pressed_holo_light.9.png
index 1352a17..2b43cde 100644
--- a/core/res/res/drawable-xxhdpi/list_pressed_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/list_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/list_section_divider_holo_dark.9.png b/core/res/res/drawable-xxhdpi/list_section_divider_holo_dark.9.png
index 61f8915..a4c9f968 100644
--- a/core/res/res/drawable-xxhdpi/list_section_divider_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/list_section_divider_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/list_section_divider_holo_light.9.png b/core/res/res/drawable-xxhdpi/list_section_divider_holo_light.9.png
index 5ae4882..d8d1f31 100644
--- a/core/res/res/drawable-xxhdpi/list_section_divider_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/list_section_divider_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/list_section_divider_mtrl_alpha.9.png b/core/res/res/drawable-xxhdpi/list_section_divider_mtrl_alpha.9.png
index 491fab9..9c4211d 100644
--- a/core/res/res/drawable-xxhdpi/list_section_divider_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xxhdpi/list_section_divider_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/list_selected_holo_dark.9.png b/core/res/res/drawable-xxhdpi/list_selected_holo_dark.9.png
index 922cff7..13c94b0 100644
--- a/core/res/res/drawable-xxhdpi/list_selected_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/list_selected_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/list_selected_holo_light.9.png b/core/res/res/drawable-xxhdpi/list_selected_holo_light.9.png
index 0f58325..86bc922 100644
--- a/core/res/res/drawable-xxhdpi/list_selected_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/list_selected_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/list_selector_background_disabled.9.png b/core/res/res/drawable-xxhdpi/list_selector_background_disabled.9.png
index e662b69..8eb01fa 100644
--- a/core/res/res/drawable-xxhdpi/list_selector_background_disabled.9.png
+++ b/core/res/res/drawable-xxhdpi/list_selector_background_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/list_selector_background_focus.9.png b/core/res/res/drawable-xxhdpi/list_selector_background_focus.9.png
index 5167387..53be316 100644
--- a/core/res/res/drawable-xxhdpi/list_selector_background_focus.9.png
+++ b/core/res/res/drawable-xxhdpi/list_selector_background_focus.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/list_selector_background_longpress.9.png b/core/res/res/drawable-xxhdpi/list_selector_background_longpress.9.png
index 4d83885..913fb50 100644
--- a/core/res/res/drawable-xxhdpi/list_selector_background_longpress.9.png
+++ b/core/res/res/drawable-xxhdpi/list_selector_background_longpress.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/list_selector_background_pressed.9.png b/core/res/res/drawable-xxhdpi/list_selector_background_pressed.9.png
index 2f93cbf..bd33526 100644
--- a/core/res/res/drawable-xxhdpi/list_selector_background_pressed.9.png
+++ b/core/res/res/drawable-xxhdpi/list_selector_background_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/lockscreen_protection_pattern.png b/core/res/res/drawable-xxhdpi/lockscreen_protection_pattern.png
index 5521eb6..2315ac8 100644
--- a/core/res/res/drawable-xxhdpi/lockscreen_protection_pattern.png
+++ b/core/res/res/drawable-xxhdpi/lockscreen_protection_pattern.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/magnified_region_frame.9.png b/core/res/res/drawable-xxhdpi/magnified_region_frame.9.png
index 09ee1c3..3d636f1 100644
--- a/core/res/res/drawable-xxhdpi/magnified_region_frame.9.png
+++ b/core/res/res/drawable-xxhdpi/magnified_region_frame.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/menu_dropdown_panel_holo_dark.9.png b/core/res/res/drawable-xxhdpi/menu_dropdown_panel_holo_dark.9.png
index e87e372..38f56a4 100644
--- a/core/res/res/drawable-xxhdpi/menu_dropdown_panel_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/menu_dropdown_panel_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/menu_dropdown_panel_holo_light.9.png b/core/res/res/drawable-xxhdpi/menu_dropdown_panel_holo_light.9.png
index 6ca7814..423664a 100644
--- a/core/res/res/drawable-xxhdpi/menu_dropdown_panel_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/menu_dropdown_panel_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/menu_hardkey_panel_holo_dark.9.png b/core/res/res/drawable-xxhdpi/menu_hardkey_panel_holo_dark.9.png
index c933eab..f916b19 100644
--- a/core/res/res/drawable-xxhdpi/menu_hardkey_panel_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/menu_hardkey_panel_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/menu_hardkey_panel_holo_light.9.png b/core/res/res/drawable-xxhdpi/menu_hardkey_panel_holo_light.9.png
index 112f939..6524bf4 100644
--- a/core/res/res/drawable-xxhdpi/menu_hardkey_panel_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/menu_hardkey_panel_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/menu_popup_panel_holo_dark.9.png b/core/res/res/drawable-xxhdpi/menu_popup_panel_holo_dark.9.png
index 90489bc..82c91f1 100644
--- a/core/res/res/drawable-xxhdpi/menu_popup_panel_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/menu_popup_panel_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/menu_popup_panel_holo_light.9.png b/core/res/res/drawable-xxhdpi/menu_popup_panel_holo_light.9.png
index 472c3d3..cfc0a52 100644
--- a/core/res/res/drawable-xxhdpi/menu_popup_panel_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/menu_popup_panel_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_down_disabled_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/numberpicker_down_disabled_focused_holo_dark.png
index 6f0a88c..fd837ae 100644
--- a/core/res/res/drawable-xxhdpi/numberpicker_down_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/numberpicker_down_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_down_disabled_focused_holo_light.png b/core/res/res/drawable-xxhdpi/numberpicker_down_disabled_focused_holo_light.png
index ea965c5..2d8ca30 100644
--- a/core/res/res/drawable-xxhdpi/numberpicker_down_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/numberpicker_down_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_down_disabled_holo_dark.png b/core/res/res/drawable-xxhdpi/numberpicker_down_disabled_holo_dark.png
index 822df62..79f62f9 100644
--- a/core/res/res/drawable-xxhdpi/numberpicker_down_disabled_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/numberpicker_down_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_down_disabled_holo_light.png b/core/res/res/drawable-xxhdpi/numberpicker_down_disabled_holo_light.png
index b17dd91..096ce3e 100644
--- a/core/res/res/drawable-xxhdpi/numberpicker_down_disabled_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/numberpicker_down_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_down_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/numberpicker_down_focused_holo_dark.png
index b558db7..8f9ddec 100644
--- a/core/res/res/drawable-xxhdpi/numberpicker_down_focused_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/numberpicker_down_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_down_focused_holo_light.png b/core/res/res/drawable-xxhdpi/numberpicker_down_focused_holo_light.png
index 5121bc0..308872b 100644
--- a/core/res/res/drawable-xxhdpi/numberpicker_down_focused_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/numberpicker_down_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_down_longpressed_holo_dark.png b/core/res/res/drawable-xxhdpi/numberpicker_down_longpressed_holo_dark.png
index 166e08c..2ffa761 100644
--- a/core/res/res/drawable-xxhdpi/numberpicker_down_longpressed_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/numberpicker_down_longpressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_down_longpressed_holo_light.png b/core/res/res/drawable-xxhdpi/numberpicker_down_longpressed_holo_light.png
index 166e08c..2ffa761 100644
--- a/core/res/res/drawable-xxhdpi/numberpicker_down_longpressed_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/numberpicker_down_longpressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_down_normal_holo_dark.png b/core/res/res/drawable-xxhdpi/numberpicker_down_normal_holo_dark.png
index 3f2e813..04f8d9f 100644
--- a/core/res/res/drawable-xxhdpi/numberpicker_down_normal_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/numberpicker_down_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_down_normal_holo_light.png b/core/res/res/drawable-xxhdpi/numberpicker_down_normal_holo_light.png
index 9026c12..945d4f9 100644
--- a/core/res/res/drawable-xxhdpi/numberpicker_down_normal_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/numberpicker_down_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_down_pressed_holo_dark.png b/core/res/res/drawable-xxhdpi/numberpicker_down_pressed_holo_dark.png
index 2a24398..b99440d 100644
--- a/core/res/res/drawable-xxhdpi/numberpicker_down_pressed_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/numberpicker_down_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_down_pressed_holo_light.png b/core/res/res/drawable-xxhdpi/numberpicker_down_pressed_holo_light.png
index 2a24398..b99440d 100644
--- a/core/res/res/drawable-xxhdpi/numberpicker_down_pressed_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/numberpicker_down_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_selection_divider.9.png b/core/res/res/drawable-xxhdpi/numberpicker_selection_divider.9.png
index b7a9940..dc675f3 100644
--- a/core/res/res/drawable-xxhdpi/numberpicker_selection_divider.9.png
+++ b/core/res/res/drawable-xxhdpi/numberpicker_selection_divider.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_up_disabled_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/numberpicker_up_disabled_focused_holo_dark.png
index a4eb1a5..30d3e60 100644
--- a/core/res/res/drawable-xxhdpi/numberpicker_up_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/numberpicker_up_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_up_disabled_focused_holo_light.png b/core/res/res/drawable-xxhdpi/numberpicker_up_disabled_focused_holo_light.png
index b43b0c2..54fc140 100644
--- a/core/res/res/drawable-xxhdpi/numberpicker_up_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/numberpicker_up_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_up_disabled_holo_dark.png b/core/res/res/drawable-xxhdpi/numberpicker_up_disabled_holo_dark.png
index 81b68fc..70dfc68 100644
--- a/core/res/res/drawable-xxhdpi/numberpicker_up_disabled_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/numberpicker_up_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_up_disabled_holo_light.png b/core/res/res/drawable-xxhdpi/numberpicker_up_disabled_holo_light.png
index 91b2f2f..a3707ab 100644
--- a/core/res/res/drawable-xxhdpi/numberpicker_up_disabled_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/numberpicker_up_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_up_focused_holo_dark.png b/core/res/res/drawable-xxhdpi/numberpicker_up_focused_holo_dark.png
index 82da07e..5f6c81a 100644
--- a/core/res/res/drawable-xxhdpi/numberpicker_up_focused_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/numberpicker_up_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_up_focused_holo_light.png b/core/res/res/drawable-xxhdpi/numberpicker_up_focused_holo_light.png
index d7c2f34..df10265 100644
--- a/core/res/res/drawable-xxhdpi/numberpicker_up_focused_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/numberpicker_up_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_up_longpressed_holo_dark.png b/core/res/res/drawable-xxhdpi/numberpicker_up_longpressed_holo_dark.png
index 1bc2bf1..ad54f83 100644
--- a/core/res/res/drawable-xxhdpi/numberpicker_up_longpressed_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/numberpicker_up_longpressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_up_longpressed_holo_light.png b/core/res/res/drawable-xxhdpi/numberpicker_up_longpressed_holo_light.png
index 1bc2bf1..ad54f83 100644
--- a/core/res/res/drawable-xxhdpi/numberpicker_up_longpressed_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/numberpicker_up_longpressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_up_normal_holo_dark.png b/core/res/res/drawable-xxhdpi/numberpicker_up_normal_holo_dark.png
index 0fd9b05..07365b8 100644
--- a/core/res/res/drawable-xxhdpi/numberpicker_up_normal_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/numberpicker_up_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_up_normal_holo_light.png b/core/res/res/drawable-xxhdpi/numberpicker_up_normal_holo_light.png
index 9f6a470..d5fa5e4 100644
--- a/core/res/res/drawable-xxhdpi/numberpicker_up_normal_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/numberpicker_up_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_up_pressed_holo_dark.png b/core/res/res/drawable-xxhdpi/numberpicker_up_pressed_holo_dark.png
index 35905ea..1a71f35 100644
--- a/core/res/res/drawable-xxhdpi/numberpicker_up_pressed_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/numberpicker_up_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/numberpicker_up_pressed_holo_light.png b/core/res/res/drawable-xxhdpi/numberpicker_up_pressed_holo_light.png
index 35905ea..1a71f35 100644
--- a/core/res/res/drawable-xxhdpi/numberpicker_up_pressed_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/numberpicker_up_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/panel_bg_holo_dark.9.png b/core/res/res/drawable-xxhdpi/panel_bg_holo_dark.9.png
index 8993469..1a72d10 100644
--- a/core/res/res/drawable-xxhdpi/panel_bg_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/panel_bg_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/panel_bg_holo_light.9.png b/core/res/res/drawable-xxhdpi/panel_bg_holo_light.9.png
index 38ec76c..ac8f56d 100644
--- a/core/res/res/drawable-xxhdpi/panel_bg_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/panel_bg_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_accessibility_features.png b/core/res/res/drawable-xxhdpi/perm_group_accessibility_features.png
index 5a63b68..c98e5e9 100644
--- a/core/res/res/drawable-xxhdpi/perm_group_accessibility_features.png
+++ b/core/res/res/drawable-xxhdpi/perm_group_accessibility_features.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_affects_battery.png b/core/res/res/drawable-xxhdpi/perm_group_affects_battery.png
index 63561be..a44dd49 100644
--- a/core/res/res/drawable-xxhdpi/perm_group_affects_battery.png
+++ b/core/res/res/drawable-xxhdpi/perm_group_affects_battery.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_app_info.png b/core/res/res/drawable-xxhdpi/perm_group_app_info.png
index fc407f3..3274a74 100644
--- a/core/res/res/drawable-xxhdpi/perm_group_app_info.png
+++ b/core/res/res/drawable-xxhdpi/perm_group_app_info.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_audio_settings.png b/core/res/res/drawable-xxhdpi/perm_group_audio_settings.png
index 23b5d97..42dc723 100644
--- a/core/res/res/drawable-xxhdpi/perm_group_audio_settings.png
+++ b/core/res/res/drawable-xxhdpi/perm_group_audio_settings.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_bluetooth.png b/core/res/res/drawable-xxhdpi/perm_group_bluetooth.png
index 2dc9b23..964f69e 100644
--- a/core/res/res/drawable-xxhdpi/perm_group_bluetooth.png
+++ b/core/res/res/drawable-xxhdpi/perm_group_bluetooth.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_bookmarks.png b/core/res/res/drawable-xxhdpi/perm_group_bookmarks.png
index 883bad3..5aea88a 100644
--- a/core/res/res/drawable-xxhdpi/perm_group_bookmarks.png
+++ b/core/res/res/drawable-xxhdpi/perm_group_bookmarks.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_device_alarms.png b/core/res/res/drawable-xxhdpi/perm_group_device_alarms.png
index 12ab22f..4fa25bd 100644
--- a/core/res/res/drawable-xxhdpi/perm_group_device_alarms.png
+++ b/core/res/res/drawable-xxhdpi/perm_group_device_alarms.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_display.png b/core/res/res/drawable-xxhdpi/perm_group_display.png
index 44e695e..8bf3169 100644
--- a/core/res/res/drawable-xxhdpi/perm_group_display.png
+++ b/core/res/res/drawable-xxhdpi/perm_group_display.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_network.png b/core/res/res/drawable-xxhdpi/perm_group_network.png
index 4bdb1bad..b2c93ff 100644
--- a/core/res/res/drawable-xxhdpi/perm_group_network.png
+++ b/core/res/res/drawable-xxhdpi/perm_group_network.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_personal_info.png b/core/res/res/drawable-xxhdpi/perm_group_personal_info.png
index c81a2a5..f917db7 100644
--- a/core/res/res/drawable-xxhdpi/perm_group_personal_info.png
+++ b/core/res/res/drawable-xxhdpi/perm_group_personal_info.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_screenlock.png b/core/res/res/drawable-xxhdpi/perm_group_screenlock.png
index 3097363..469f114 100644
--- a/core/res/res/drawable-xxhdpi/perm_group_screenlock.png
+++ b/core/res/res/drawable-xxhdpi/perm_group_screenlock.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_shortrange_network.png b/core/res/res/drawable-xxhdpi/perm_group_shortrange_network.png
index 6b21718..d70945a 100644
--- a/core/res/res/drawable-xxhdpi/perm_group_shortrange_network.png
+++ b/core/res/res/drawable-xxhdpi/perm_group_shortrange_network.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_status_bar.png b/core/res/res/drawable-xxhdpi/perm_group_status_bar.png
index eda264b..64541ee 100644
--- a/core/res/res/drawable-xxhdpi/perm_group_status_bar.png
+++ b/core/res/res/drawable-xxhdpi/perm_group_status_bar.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_sync_settings.png b/core/res/res/drawable-xxhdpi/perm_group_sync_settings.png
index 15ab0fc..c321977 100644
--- a/core/res/res/drawable-xxhdpi/perm_group_sync_settings.png
+++ b/core/res/res/drawable-xxhdpi/perm_group_sync_settings.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_system_clock.png b/core/res/res/drawable-xxhdpi/perm_group_system_clock.png
index 9149497..b287736 100644
--- a/core/res/res/drawable-xxhdpi/perm_group_system_clock.png
+++ b/core/res/res/drawable-xxhdpi/perm_group_system_clock.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_system_tools.png b/core/res/res/drawable-xxhdpi/perm_group_system_tools.png
index 0332e40..3077b76 100644
--- a/core/res/res/drawable-xxhdpi/perm_group_system_tools.png
+++ b/core/res/res/drawable-xxhdpi/perm_group_system_tools.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_voicemail.png b/core/res/res/drawable-xxhdpi/perm_group_voicemail.png
index 8f08516..13085a5 100644
--- a/core/res/res/drawable-xxhdpi/perm_group_voicemail.png
+++ b/core/res/res/drawable-xxhdpi/perm_group_voicemail.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_wallpaper.png b/core/res/res/drawable-xxhdpi/perm_group_wallpaper.png
index 9c87e9a..f155a31 100644
--- a/core/res/res/drawable-xxhdpi/perm_group_wallpaper.png
+++ b/core/res/res/drawable-xxhdpi/perm_group_wallpaper.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/pointer_arrow.png b/core/res/res/drawable-xxhdpi/pointer_arrow.png
index 65e0320..4031f16 100644
--- a/core/res/res/drawable-xxhdpi/pointer_arrow.png
+++ b/core/res/res/drawable-xxhdpi/pointer_arrow.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/popup_background_mtrl_mult.9.png b/core/res/res/drawable-xxhdpi/popup_background_mtrl_mult.9.png
index fb7d715..8067407 100644
--- a/core/res/res/drawable-xxhdpi/popup_background_mtrl_mult.9.png
+++ b/core/res/res/drawable-xxhdpi/popup_background_mtrl_mult.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/popup_inline_error_above_holo_dark_am.9.png b/core/res/res/drawable-xxhdpi/popup_inline_error_above_holo_dark_am.9.png
index 251660a..836130c 100644
--- a/core/res/res/drawable-xxhdpi/popup_inline_error_above_holo_dark_am.9.png
+++ b/core/res/res/drawable-xxhdpi/popup_inline_error_above_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/popup_inline_error_above_holo_light_am.9.png b/core/res/res/drawable-xxhdpi/popup_inline_error_above_holo_light_am.9.png
index 12b1e64..526a29c 100644
--- a/core/res/res/drawable-xxhdpi/popup_inline_error_above_holo_light_am.9.png
+++ b/core/res/res/drawable-xxhdpi/popup_inline_error_above_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/popup_inline_error_holo_dark_am.9.png b/core/res/res/drawable-xxhdpi/popup_inline_error_holo_dark_am.9.png
index 5d389af..a8868b5 100644
--- a/core/res/res/drawable-xxhdpi/popup_inline_error_holo_dark_am.9.png
+++ b/core/res/res/drawable-xxhdpi/popup_inline_error_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/popup_inline_error_holo_light_am.9.png b/core/res/res/drawable-xxhdpi/popup_inline_error_holo_light_am.9.png
index 5e3c01b..023b85d 100644
--- a/core/res/res/drawable-xxhdpi/popup_inline_error_holo_light_am.9.png
+++ b/core/res/res/drawable-xxhdpi/popup_inline_error_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/presence_audio_away.png b/core/res/res/drawable-xxhdpi/presence_audio_away.png
index e8e2b1a..bb99fbb 100644
--- a/core/res/res/drawable-xxhdpi/presence_audio_away.png
+++ b/core/res/res/drawable-xxhdpi/presence_audio_away.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/presence_audio_busy.png b/core/res/res/drawable-xxhdpi/presence_audio_busy.png
index 824b5be..2e95508 100644
--- a/core/res/res/drawable-xxhdpi/presence_audio_busy.png
+++ b/core/res/res/drawable-xxhdpi/presence_audio_busy.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/presence_audio_online.png b/core/res/res/drawable-xxhdpi/presence_audio_online.png
index 6b3cd2d..def064c 100644
--- a/core/res/res/drawable-xxhdpi/presence_audio_online.png
+++ b/core/res/res/drawable-xxhdpi/presence_audio_online.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/presence_away.png b/core/res/res/drawable-xxhdpi/presence_away.png
index 217f4e9..02f9a23 100644
--- a/core/res/res/drawable-xxhdpi/presence_away.png
+++ b/core/res/res/drawable-xxhdpi/presence_away.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/presence_busy.png b/core/res/res/drawable-xxhdpi/presence_busy.png
index 9416720..15099cf 100644
--- a/core/res/res/drawable-xxhdpi/presence_busy.png
+++ b/core/res/res/drawable-xxhdpi/presence_busy.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/presence_invisible.png b/core/res/res/drawable-xxhdpi/presence_invisible.png
index 72ada9c..826247a 100644
--- a/core/res/res/drawable-xxhdpi/presence_invisible.png
+++ b/core/res/res/drawable-xxhdpi/presence_invisible.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/presence_offline.png b/core/res/res/drawable-xxhdpi/presence_offline.png
index bc71d3a..8318146 100644
--- a/core/res/res/drawable-xxhdpi/presence_offline.png
+++ b/core/res/res/drawable-xxhdpi/presence_offline.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/presence_online.png b/core/res/res/drawable-xxhdpi/presence_online.png
index 501a75d..c096fba 100644
--- a/core/res/res/drawable-xxhdpi/presence_online.png
+++ b/core/res/res/drawable-xxhdpi/presence_online.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/presence_video_away.png b/core/res/res/drawable-xxhdpi/presence_video_away.png
index 1379bc0..449d86d 100644
--- a/core/res/res/drawable-xxhdpi/presence_video_away.png
+++ b/core/res/res/drawable-xxhdpi/presence_video_away.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/presence_video_busy.png b/core/res/res/drawable-xxhdpi/presence_video_busy.png
index d90297c..1d8bda5 100644
--- a/core/res/res/drawable-xxhdpi/presence_video_busy.png
+++ b/core/res/res/drawable-xxhdpi/presence_video_busy.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/presence_video_online.png b/core/res/res/drawable-xxhdpi/presence_video_online.png
index 4186408..dc5599e 100644
--- a/core/res/res/drawable-xxhdpi/presence_video_online.png
+++ b/core/res/res/drawable-xxhdpi/presence_video_online.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/progress_bg_holo_dark.9.png b/core/res/res/drawable-xxhdpi/progress_bg_holo_dark.9.png
index 2e8c2e5..b67ddd5 100644
--- a/core/res/res/drawable-xxhdpi/progress_bg_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/progress_bg_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/progress_bg_holo_light.9.png b/core/res/res/drawable-xxhdpi/progress_bg_holo_light.9.png
index fb146c3..79d299c 100644
--- a/core/res/res/drawable-xxhdpi/progress_bg_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/progress_bg_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/progress_primary_holo_dark.9.png b/core/res/res/drawable-xxhdpi/progress_primary_holo_dark.9.png
index 36078f9..0c54e94 100644
--- a/core/res/res/drawable-xxhdpi/progress_primary_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/progress_primary_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/progress_primary_holo_light.9.png b/core/res/res/drawable-xxhdpi/progress_primary_holo_light.9.png
index add4d38..1d88207 100644
--- a/core/res/res/drawable-xxhdpi/progress_primary_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/progress_primary_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/progress_secondary_holo_dark.9.png b/core/res/res/drawable-xxhdpi/progress_secondary_holo_dark.9.png
index 90b56fc8..b774dcd 100644
--- a/core/res/res/drawable-xxhdpi/progress_secondary_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/progress_secondary_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/progress_secondary_holo_light.9.png b/core/res/res/drawable-xxhdpi/progress_secondary_holo_light.9.png
index 28b53dd..b774dcd 100644
--- a/core/res/res/drawable-xxhdpi/progress_secondary_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/progress_secondary_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo1.png b/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo1.png
index e751345..e5bc992 100644
--- a/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo1.png
+++ b/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo1.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo2.png b/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo2.png
index 663965f..e0738877 100644
--- a/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo2.png
+++ b/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo2.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo3.png b/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo3.png
index 3574c9a..69e5792 100644
--- a/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo3.png
+++ b/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo3.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo4.png b/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo4.png
index a289d33..dbf3fb3 100644
--- a/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo4.png
+++ b/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo4.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo5.png b/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo5.png
index 6fa2fbb..f3804cb 100644
--- a/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo5.png
+++ b/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo5.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo6.png b/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo6.png
index 0117543..e53e3b1 100644
--- a/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo6.png
+++ b/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo6.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo7.png b/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo7.png
index 681fe1d..357cf8a 100644
--- a/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo7.png
+++ b/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo7.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo8.png b/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo8.png
index bbc3999..0811ef0 100644
--- a/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo8.png
+++ b/core/res/res/drawable-xxhdpi/progressbar_indeterminate_holo8.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_focused_dark_am.9.png b/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_focused_dark_am.9.png
index 8eda0f1..dc18580 100644
--- a/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_focused_dark_am.9.png
+++ b/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_focused_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_focused_light_am.9.png b/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_focused_light_am.9.png
index c7cd27a..4cfd384 100644
--- a/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_focused_light_am.9.png
+++ b/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_focused_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_normal_dark_am.9.png b/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_normal_dark_am.9.png
index 09c8cbd..2daee62 100644
--- a/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_normal_dark_am.9.png
+++ b/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_normal_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_normal_light_am.9.png b/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_normal_light_am.9.png
index d0a5a71..e20f955 100644
--- a/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_normal_light_am.9.png
+++ b/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_normal_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_pressed_dark_am.9.png b/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_pressed_dark_am.9.png
index 432436f..0a643c0 100644
--- a/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_pressed_dark_am.9.png
+++ b/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_pressed_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_pressed_light_am.9.png b/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_pressed_light_am.9.png
index b18aed6..897751da 100644
--- a/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_pressed_light_am.9.png
+++ b/core/res/res/drawable-xxhdpi/quickcontact_badge_overlay_pressed_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/rate_star_big_half_holo_dark.png b/core/res/res/drawable-xxhdpi/rate_star_big_half_holo_dark.png
index ede3db5..e433b3b 100644
--- a/core/res/res/drawable-xxhdpi/rate_star_big_half_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/rate_star_big_half_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/rate_star_big_half_holo_light.png b/core/res/res/drawable-xxhdpi/rate_star_big_half_holo_light.png
index 906dbe1..4405bb9 100644
--- a/core/res/res/drawable-xxhdpi/rate_star_big_half_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/rate_star_big_half_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/rate_star_big_off_holo_dark.png b/core/res/res/drawable-xxhdpi/rate_star_big_off_holo_dark.png
index cff58d3..e7597b5 100644
--- a/core/res/res/drawable-xxhdpi/rate_star_big_off_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/rate_star_big_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/rate_star_big_off_holo_light.png b/core/res/res/drawable-xxhdpi/rate_star_big_off_holo_light.png
index 7e1a770..13c2229 100644
--- a/core/res/res/drawable-xxhdpi/rate_star_big_off_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/rate_star_big_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/rate_star_big_on_holo_dark.png b/core/res/res/drawable-xxhdpi/rate_star_big_on_holo_dark.png
index ab3f4d3..394bc99 100644
--- a/core/res/res/drawable-xxhdpi/rate_star_big_on_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/rate_star_big_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/rate_star_big_on_holo_light.png b/core/res/res/drawable-xxhdpi/rate_star_big_on_holo_light.png
index ab7a496..797ab4d 100644
--- a/core/res/res/drawable-xxhdpi/rate_star_big_on_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/rate_star_big_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/rate_star_med_half_holo_dark.png b/core/res/res/drawable-xxhdpi/rate_star_med_half_holo_dark.png
index 8bb8aa0..6957947 100644
--- a/core/res/res/drawable-xxhdpi/rate_star_med_half_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/rate_star_med_half_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/rate_star_med_half_holo_light.png b/core/res/res/drawable-xxhdpi/rate_star_med_half_holo_light.png
index 44e6696..1bd8222 100644
--- a/core/res/res/drawable-xxhdpi/rate_star_med_half_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/rate_star_med_half_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/rate_star_med_off_holo_dark.png b/core/res/res/drawable-xxhdpi/rate_star_med_off_holo_dark.png
index 94ec824..abbb947 100644
--- a/core/res/res/drawable-xxhdpi/rate_star_med_off_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/rate_star_med_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/rate_star_med_off_holo_light.png b/core/res/res/drawable-xxhdpi/rate_star_med_off_holo_light.png
index 0a12fc9..38384c5 100644
--- a/core/res/res/drawable-xxhdpi/rate_star_med_off_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/rate_star_med_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/rate_star_med_on_holo_dark.png b/core/res/res/drawable-xxhdpi/rate_star_med_on_holo_dark.png
index 4894658..23d885d 100644
--- a/core/res/res/drawable-xxhdpi/rate_star_med_on_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/rate_star_med_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/rate_star_med_on_holo_light.png b/core/res/res/drawable-xxhdpi/rate_star_med_on_holo_light.png
index 4bb8a73..88d34a9 100644
--- a/core/res/res/drawable-xxhdpi/rate_star_med_on_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/rate_star_med_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/rate_star_small_half_holo_dark.png b/core/res/res/drawable-xxhdpi/rate_star_small_half_holo_dark.png
index 9e215d7..ff1e6b4 100644
--- a/core/res/res/drawable-xxhdpi/rate_star_small_half_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/rate_star_small_half_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/rate_star_small_half_holo_light.png b/core/res/res/drawable-xxhdpi/rate_star_small_half_holo_light.png
index e6ce596..0fa028f 100644
--- a/core/res/res/drawable-xxhdpi/rate_star_small_half_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/rate_star_small_half_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/rate_star_small_off_holo_dark.png b/core/res/res/drawable-xxhdpi/rate_star_small_off_holo_dark.png
index 2a9fc21..113170f 100644
--- a/core/res/res/drawable-xxhdpi/rate_star_small_off_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/rate_star_small_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/rate_star_small_off_holo_light.png b/core/res/res/drawable-xxhdpi/rate_star_small_off_holo_light.png
index 42cad5e..bc7e15d 100644
--- a/core/res/res/drawable-xxhdpi/rate_star_small_off_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/rate_star_small_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/rate_star_small_on_holo_dark.png b/core/res/res/drawable-xxhdpi/rate_star_small_on_holo_dark.png
index 0612b25..0289bad 100644
--- a/core/res/res/drawable-xxhdpi/rate_star_small_on_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/rate_star_small_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/rate_star_small_on_holo_light.png b/core/res/res/drawable-xxhdpi/rate_star_small_on_holo_light.png
index aaa3d0f..991b949 100644
--- a/core/res/res/drawable-xxhdpi/rate_star_small_on_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/rate_star_small_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrollbar_handle_holo_dark.9.png b/core/res/res/drawable-xxhdpi/scrollbar_handle_holo_dark.9.png
index 66b3e9d..69c6ff7 100644
--- a/core/res/res/drawable-xxhdpi/scrollbar_handle_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/scrollbar_handle_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrollbar_handle_holo_light.9.png b/core/res/res/drawable-xxhdpi/scrollbar_handle_holo_light.9.png
index 5fbd723..f26f62a 100644
--- a/core/res/res/drawable-xxhdpi/scrollbar_handle_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/scrollbar_handle_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_control_disabled_holo.png b/core/res/res/drawable-xxhdpi/scrubber_control_disabled_holo.png
index 74b7431..6a50d76 100644
--- a/core/res/res/drawable-xxhdpi/scrubber_control_disabled_holo.png
+++ b/core/res/res/drawable-xxhdpi/scrubber_control_disabled_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_control_focused_holo.png b/core/res/res/drawable-xxhdpi/scrubber_control_focused_holo.png
index 2945fbd..4427197 100644
--- a/core/res/res/drawable-xxhdpi/scrubber_control_focused_holo.png
+++ b/core/res/res/drawable-xxhdpi/scrubber_control_focused_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_control_normal_holo.png b/core/res/res/drawable-xxhdpi/scrubber_control_normal_holo.png
index 9dde7da..be21080 100644
--- a/core/res/res/drawable-xxhdpi/scrubber_control_normal_holo.png
+++ b/core/res/res/drawable-xxhdpi/scrubber_control_normal_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_control_on_mtrl_alpha.png b/core/res/res/drawable-xxhdpi/scrubber_control_on_mtrl_alpha.png
index caabc2c..03c235b4 100644
--- a/core/res/res/drawable-xxhdpi/scrubber_control_on_mtrl_alpha.png
+++ b/core/res/res/drawable-xxhdpi/scrubber_control_on_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_control_on_pressed_mtrl_alpha.png b/core/res/res/drawable-xxhdpi/scrubber_control_on_pressed_mtrl_alpha.png
index b46ee1c..9bfab3a 100644
--- a/core/res/res/drawable-xxhdpi/scrubber_control_on_pressed_mtrl_alpha.png
+++ b/core/res/res/drawable-xxhdpi/scrubber_control_on_pressed_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_control_pressed_holo.png b/core/res/res/drawable-xxhdpi/scrubber_control_pressed_holo.png
index 8afbb6d..90f55af 100644
--- a/core/res/res/drawable-xxhdpi/scrubber_control_pressed_holo.png
+++ b/core/res/res/drawable-xxhdpi/scrubber_control_pressed_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_primary_holo.9.png b/core/res/res/drawable-xxhdpi/scrubber_primary_holo.9.png
index 209df49..12735d4 100644
--- a/core/res/res/drawable-xxhdpi/scrubber_primary_holo.9.png
+++ b/core/res/res/drawable-xxhdpi/scrubber_primary_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_primary_mtrl_alpha.9.png b/core/res/res/drawable-xxhdpi/scrubber_primary_mtrl_alpha.9.png
index 6a82af5..f34ad3b 100644
--- a/core/res/res/drawable-xxhdpi/scrubber_primary_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xxhdpi/scrubber_primary_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_secondary_holo.9.png b/core/res/res/drawable-xxhdpi/scrubber_secondary_holo.9.png
index 3dbcc48..45e0d00 100644
--- a/core/res/res/drawable-xxhdpi/scrubber_secondary_holo.9.png
+++ b/core/res/res/drawable-xxhdpi/scrubber_secondary_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_track_holo_dark.9.png b/core/res/res/drawable-xxhdpi/scrubber_track_holo_dark.9.png
index 4014860..7101aab 100644
--- a/core/res/res/drawable-xxhdpi/scrubber_track_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/scrubber_track_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_track_holo_light.9.png b/core/res/res/drawable-xxhdpi/scrubber_track_holo_light.9.png
index 1a6f577..d5d86ee 100644
--- a/core/res/res/drawable-xxhdpi/scrubber_track_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/scrubber_track_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_track_mtrl_alpha.9.png b/core/res/res/drawable-xxhdpi/scrubber_track_mtrl_alpha.9.png
index c3791fc..a6a23db 100644
--- a/core/res/res/drawable-xxhdpi/scrubber_track_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xxhdpi/scrubber_track_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_16_inner_holo.png b/core/res/res/drawable-xxhdpi/spinner_16_inner_holo.png
index 30f0db3..b98d96a 100644
--- a/core/res/res/drawable-xxhdpi/spinner_16_inner_holo.png
+++ b/core/res/res/drawable-xxhdpi/spinner_16_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_16_outer_holo.png b/core/res/res/drawable-xxhdpi/spinner_16_outer_holo.png
index d0729da..ad0fd42 100644
--- a/core/res/res/drawable-xxhdpi/spinner_16_outer_holo.png
+++ b/core/res/res/drawable-xxhdpi/spinner_16_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_48_inner_holo.png b/core/res/res/drawable-xxhdpi/spinner_48_inner_holo.png
index eca7a46..6a6ccc4 100644
--- a/core/res/res/drawable-xxhdpi/spinner_48_inner_holo.png
+++ b/core/res/res/drawable-xxhdpi/spinner_48_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_48_outer_holo.png b/core/res/res/drawable-xxhdpi/spinner_48_outer_holo.png
index 3511d52..6f107cc 100644
--- a/core/res/res/drawable-xxhdpi/spinner_48_outer_holo.png
+++ b/core/res/res/drawable-xxhdpi/spinner_48_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_76_inner_holo.png b/core/res/res/drawable-xxhdpi/spinner_76_inner_holo.png
index 21ad59f..ed7b3b1 100644
--- a/core/res/res/drawable-xxhdpi/spinner_76_inner_holo.png
+++ b/core/res/res/drawable-xxhdpi/spinner_76_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_76_outer_holo.png b/core/res/res/drawable-xxhdpi/spinner_76_outer_holo.png
index 471d78c..5dc9681 100644
--- a/core/res/res/drawable-xxhdpi/spinner_76_outer_holo.png
+++ b/core/res/res/drawable-xxhdpi/spinner_76_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_ab_activated_holo_dark.9.png b/core/res/res/drawable-xxhdpi/spinner_ab_activated_holo_dark.9.png
index 6be9e6b..9f7d9bb 100644
--- a/core/res/res/drawable-xxhdpi/spinner_ab_activated_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/spinner_ab_activated_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_ab_activated_holo_light.9.png b/core/res/res/drawable-xxhdpi/spinner_ab_activated_holo_light.9.png
index 0b9a077..9f7d9bb 100644
--- a/core/res/res/drawable-xxhdpi/spinner_ab_activated_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/spinner_ab_activated_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_ab_default_holo_dark_am.9.png b/core/res/res/drawable-xxhdpi/spinner_ab_default_holo_dark_am.9.png
index 71075a7..087e72d 100644
--- a/core/res/res/drawable-xxhdpi/spinner_ab_default_holo_dark_am.9.png
+++ b/core/res/res/drawable-xxhdpi/spinner_ab_default_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_ab_default_holo_light_am.9.png b/core/res/res/drawable-xxhdpi/spinner_ab_default_holo_light_am.9.png
index 6aabc3c..3435302 100644
--- a/core/res/res/drawable-xxhdpi/spinner_ab_default_holo_light_am.9.png
+++ b/core/res/res/drawable-xxhdpi/spinner_ab_default_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_ab_disabled_holo_dark_am.9.png b/core/res/res/drawable-xxhdpi/spinner_ab_disabled_holo_dark_am.9.png
index a2045e1..efcbc4a 100644
--- a/core/res/res/drawable-xxhdpi/spinner_ab_disabled_holo_dark_am.9.png
+++ b/core/res/res/drawable-xxhdpi/spinner_ab_disabled_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_ab_disabled_holo_light_am.9.png b/core/res/res/drawable-xxhdpi/spinner_ab_disabled_holo_light_am.9.png
index 1f4d161..4410fb6 100644
--- a/core/res/res/drawable-xxhdpi/spinner_ab_disabled_holo_light_am.9.png
+++ b/core/res/res/drawable-xxhdpi/spinner_ab_disabled_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_ab_focused_holo_dark_am.9.png b/core/res/res/drawable-xxhdpi/spinner_ab_focused_holo_dark_am.9.png
index 85b0634..a963d4c 100644
--- a/core/res/res/drawable-xxhdpi/spinner_ab_focused_holo_dark_am.9.png
+++ b/core/res/res/drawable-xxhdpi/spinner_ab_focused_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_ab_focused_holo_light_am.9.png b/core/res/res/drawable-xxhdpi/spinner_ab_focused_holo_light_am.9.png
index 52e29fc..b62a21d 100644
--- a/core/res/res/drawable-xxhdpi/spinner_ab_focused_holo_light_am.9.png
+++ b/core/res/res/drawable-xxhdpi/spinner_ab_focused_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_ab_pressed_holo_dark_am.9.png b/core/res/res/drawable-xxhdpi/spinner_ab_pressed_holo_dark_am.9.png
index e78bfd0..70ea623 100644
--- a/core/res/res/drawable-xxhdpi/spinner_ab_pressed_holo_dark_am.9.png
+++ b/core/res/res/drawable-xxhdpi/spinner_ab_pressed_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_ab_pressed_holo_light_am.9.png b/core/res/res/drawable-xxhdpi/spinner_ab_pressed_holo_light_am.9.png
index 66c80a2..d953652 100644
--- a/core/res/res/drawable-xxhdpi/spinner_ab_pressed_holo_light_am.9.png
+++ b/core/res/res/drawable-xxhdpi/spinner_ab_pressed_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_activated_holo_dark.9.png b/core/res/res/drawable-xxhdpi/spinner_activated_holo_dark.9.png
index b1a39e1..de4c16f 100644
--- a/core/res/res/drawable-xxhdpi/spinner_activated_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/spinner_activated_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_activated_holo_light.9.png b/core/res/res/drawable-xxhdpi/spinner_activated_holo_light.9.png
index 052f551..de4c16f 100644
--- a/core/res/res/drawable-xxhdpi/spinner_activated_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/spinner_activated_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_default_holo_dark_am.9.png b/core/res/res/drawable-xxhdpi/spinner_default_holo_dark_am.9.png
index b0020f2..b7332c2 100644
--- a/core/res/res/drawable-xxhdpi/spinner_default_holo_dark_am.9.png
+++ b/core/res/res/drawable-xxhdpi/spinner_default_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_default_holo_light_am.9.png b/core/res/res/drawable-xxhdpi/spinner_default_holo_light_am.9.png
index 32139ce..ba66d909 100644
--- a/core/res/res/drawable-xxhdpi/spinner_default_holo_light_am.9.png
+++ b/core/res/res/drawable-xxhdpi/spinner_default_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_disabled_holo.9.png b/core/res/res/drawable-xxhdpi/spinner_disabled_holo.9.png
index f666309..f8c196f 100644
--- a/core/res/res/drawable-xxhdpi/spinner_disabled_holo.9.png
+++ b/core/res/res/drawable-xxhdpi/spinner_disabled_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_disabled_holo_dark_am.9.png b/core/res/res/drawable-xxhdpi/spinner_disabled_holo_dark_am.9.png
index 7c12096..3690a49 100644
--- a/core/res/res/drawable-xxhdpi/spinner_disabled_holo_dark_am.9.png
+++ b/core/res/res/drawable-xxhdpi/spinner_disabled_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_disabled_holo_light_am.9.png b/core/res/res/drawable-xxhdpi/spinner_disabled_holo_light_am.9.png
index 4cef095..7d46a9d0 100644
--- a/core/res/res/drawable-xxhdpi/spinner_disabled_holo_light_am.9.png
+++ b/core/res/res/drawable-xxhdpi/spinner_disabled_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_focused_holo_dark_am.9.png b/core/res/res/drawable-xxhdpi/spinner_focused_holo_dark_am.9.png
index 5ab38fd..869ac86 100644
--- a/core/res/res/drawable-xxhdpi/spinner_focused_holo_dark_am.9.png
+++ b/core/res/res/drawable-xxhdpi/spinner_focused_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_focused_holo_light_am.9.png b/core/res/res/drawable-xxhdpi/spinner_focused_holo_light_am.9.png
index c40ce17..b061161 100644
--- a/core/res/res/drawable-xxhdpi/spinner_focused_holo_light_am.9.png
+++ b/core/res/res/drawable-xxhdpi/spinner_focused_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_normal_holo.9.png b/core/res/res/drawable-xxhdpi/spinner_normal_holo.9.png
index 48a23f6..584b488 100644
--- a/core/res/res/drawable-xxhdpi/spinner_normal_holo.9.png
+++ b/core/res/res/drawable-xxhdpi/spinner_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_pressed_holo_dark_am.9.png b/core/res/res/drawable-xxhdpi/spinner_pressed_holo_dark_am.9.png
index e2212a5..405ebc1 100644
--- a/core/res/res/drawable-xxhdpi/spinner_pressed_holo_dark_am.9.png
+++ b/core/res/res/drawable-xxhdpi/spinner_pressed_holo_dark_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_pressed_holo_light_am.9.png b/core/res/res/drawable-xxhdpi/spinner_pressed_holo_light_am.9.png
index 881ce7e..12b6164 100644
--- a/core/res/res/drawable-xxhdpi/spinner_pressed_holo_light_am.9.png
+++ b/core/res/res/drawable-xxhdpi/spinner_pressed_holo_light_am.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_car_mode.png b/core/res/res/drawable-xxhdpi/stat_notify_car_mode.png
index b01e00f..dd4f4de 100644
--- a/core/res/res/drawable-xxhdpi/stat_notify_car_mode.png
+++ b/core/res/res/drawable-xxhdpi/stat_notify_car_mode.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_chat.png b/core/res/res/drawable-xxhdpi/stat_notify_chat.png
index 960fdd4..d95f294 100644
--- a/core/res/res/drawable-xxhdpi/stat_notify_chat.png
+++ b/core/res/res/drawable-xxhdpi/stat_notify_chat.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_disk_full.png b/core/res/res/drawable-xxhdpi/stat_notify_disk_full.png
index cd790a6..de77c96 100644
--- a/core/res/res/drawable-xxhdpi/stat_notify_disk_full.png
+++ b/core/res/res/drawable-xxhdpi/stat_notify_disk_full.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_email_generic.png b/core/res/res/drawable-xxhdpi/stat_notify_email_generic.png
index ba98c67..22b5f14 100644
--- a/core/res/res/drawable-xxhdpi/stat_notify_email_generic.png
+++ b/core/res/res/drawable-xxhdpi/stat_notify_email_generic.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_error.png b/core/res/res/drawable-xxhdpi/stat_notify_error.png
index fa5f7a3..bc4a12c 100644
--- a/core/res/res/drawable-xxhdpi/stat_notify_error.png
+++ b/core/res/res/drawable-xxhdpi/stat_notify_error.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_gmail.png b/core/res/res/drawable-xxhdpi/stat_notify_gmail.png
index 4640e88..e012687 100644
--- a/core/res/res/drawable-xxhdpi/stat_notify_gmail.png
+++ b/core/res/res/drawable-xxhdpi/stat_notify_gmail.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_missed_call.png b/core/res/res/drawable-xxhdpi/stat_notify_missed_call.png
index 904df3b..8d61af0 100644
--- a/core/res/res/drawable-xxhdpi/stat_notify_missed_call.png
+++ b/core/res/res/drawable-xxhdpi/stat_notify_missed_call.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_mmcc_indication_icn.png b/core/res/res/drawable-xxhdpi/stat_notify_mmcc_indication_icn.png
index a648b0b..bac945d 100644
--- a/core/res/res/drawable-xxhdpi/stat_notify_mmcc_indication_icn.png
+++ b/core/res/res/drawable-xxhdpi/stat_notify_mmcc_indication_icn.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_more.png b/core/res/res/drawable-xxhdpi/stat_notify_more.png
index f3a46ec..0e9044c 100644
--- a/core/res/res/drawable-xxhdpi/stat_notify_more.png
+++ b/core/res/res/drawable-xxhdpi/stat_notify_more.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_rssi_in_range.png b/core/res/res/drawable-xxhdpi/stat_notify_rssi_in_range.png
index 86c34ed..ae0d38b 100644
--- a/core/res/res/drawable-xxhdpi/stat_notify_rssi_in_range.png
+++ b/core/res/res/drawable-xxhdpi/stat_notify_rssi_in_range.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_sdcard.png b/core/res/res/drawable-xxhdpi/stat_notify_sdcard.png
index 87e9d20..20f0d5c 100644
--- a/core/res/res/drawable-xxhdpi/stat_notify_sdcard.png
+++ b/core/res/res/drawable-xxhdpi/stat_notify_sdcard.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_sdcard_prepare.png b/core/res/res/drawable-xxhdpi/stat_notify_sdcard_prepare.png
index 735ccc9..306f5314 100644
--- a/core/res/res/drawable-xxhdpi/stat_notify_sdcard_prepare.png
+++ b/core/res/res/drawable-xxhdpi/stat_notify_sdcard_prepare.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_sdcard_usb.png b/core/res/res/drawable-xxhdpi/stat_notify_sdcard_usb.png
index e7512ed..269024c 100644
--- a/core/res/res/drawable-xxhdpi/stat_notify_sdcard_usb.png
+++ b/core/res/res/drawable-xxhdpi/stat_notify_sdcard_usb.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_sim_toolkit.png b/core/res/res/drawable-xxhdpi/stat_notify_sim_toolkit.png
index d1cf3d7..4b930a6 100644
--- a/core/res/res/drawable-xxhdpi/stat_notify_sim_toolkit.png
+++ b/core/res/res/drawable-xxhdpi/stat_notify_sim_toolkit.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_sync.png b/core/res/res/drawable-xxhdpi/stat_notify_sync.png
index 2a36702..adbe037 100644
--- a/core/res/res/drawable-xxhdpi/stat_notify_sync.png
+++ b/core/res/res/drawable-xxhdpi/stat_notify_sync.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_sync_anim0.png b/core/res/res/drawable-xxhdpi/stat_notify_sync_anim0.png
index 2a36702..adbe037 100644
--- a/core/res/res/drawable-xxhdpi/stat_notify_sync_anim0.png
+++ b/core/res/res/drawable-xxhdpi/stat_notify_sync_anim0.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_sync_error.png b/core/res/res/drawable-xxhdpi/stat_notify_sync_error.png
index db2f0e2..40d5511 100644
--- a/core/res/res/drawable-xxhdpi/stat_notify_sync_error.png
+++ b/core/res/res/drawable-xxhdpi/stat_notify_sync_error.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_voicemail.png b/core/res/res/drawable-xxhdpi/stat_notify_voicemail.png
index 71dfe68..d004083 100644
--- a/core/res/res/drawable-xxhdpi/stat_notify_voicemail.png
+++ b/core/res/res/drawable-xxhdpi/stat_notify_voicemail.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_certificate_info.png b/core/res/res/drawable-xxhdpi/stat_sys_certificate_info.png
index d96ef64..e44ea38 100644
--- a/core/res/res/drawable-xxhdpi/stat_sys_certificate_info.png
+++ b/core/res/res/drawable-xxhdpi/stat_sys_certificate_info.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_data_bluetooth.png b/core/res/res/drawable-xxhdpi/stat_sys_data_bluetooth.png
index 6dd4d7f..992ecdb 100644
--- a/core/res/res/drawable-xxhdpi/stat_sys_data_bluetooth.png
+++ b/core/res/res/drawable-xxhdpi/stat_sys_data_bluetooth.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_data_usb.png b/core/res/res/drawable-xxhdpi/stat_sys_data_usb.png
index 7fcf5cd..501b89f 100644
--- a/core/res/res/drawable-xxhdpi/stat_sys_data_usb.png
+++ b/core/res/res/drawable-xxhdpi/stat_sys_data_usb.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_data_wimax_signal_3_fully.png b/core/res/res/drawable-xxhdpi/stat_sys_data_wimax_signal_3_fully.png
index aeccbd6..080c120 100644
--- a/core/res/res/drawable-xxhdpi/stat_sys_data_wimax_signal_3_fully.png
+++ b/core/res/res/drawable-xxhdpi/stat_sys_data_wimax_signal_3_fully.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_data_wimax_signal_disconnected.png b/core/res/res/drawable-xxhdpi/stat_sys_data_wimax_signal_disconnected.png
index 3cdc45d..4e50eb4 100644
--- a/core/res/res/drawable-xxhdpi/stat_sys_data_wimax_signal_disconnected.png
+++ b/core/res/res/drawable-xxhdpi/stat_sys_data_wimax_signal_disconnected.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_download_anim0.png b/core/res/res/drawable-xxhdpi/stat_sys_download_anim0.png
index 836db12..68ecce8 100644
--- a/core/res/res/drawable-xxhdpi/stat_sys_download_anim0.png
+++ b/core/res/res/drawable-xxhdpi/stat_sys_download_anim0.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_download_anim1.png b/core/res/res/drawable-xxhdpi/stat_sys_download_anim1.png
index 5bc3add4..f8ff19d 100644
--- a/core/res/res/drawable-xxhdpi/stat_sys_download_anim1.png
+++ b/core/res/res/drawable-xxhdpi/stat_sys_download_anim1.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_download_anim2.png b/core/res/res/drawable-xxhdpi/stat_sys_download_anim2.png
index 962c450..6f7f919 100644
--- a/core/res/res/drawable-xxhdpi/stat_sys_download_anim2.png
+++ b/core/res/res/drawable-xxhdpi/stat_sys_download_anim2.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_download_anim3.png b/core/res/res/drawable-xxhdpi/stat_sys_download_anim3.png
index e1d0d55..64e2893 100644
--- a/core/res/res/drawable-xxhdpi/stat_sys_download_anim3.png
+++ b/core/res/res/drawable-xxhdpi/stat_sys_download_anim3.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_download_anim4.png b/core/res/res/drawable-xxhdpi/stat_sys_download_anim4.png
index 84420de..f8b6fce 100644
--- a/core/res/res/drawable-xxhdpi/stat_sys_download_anim4.png
+++ b/core/res/res/drawable-xxhdpi/stat_sys_download_anim4.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_download_anim5.png b/core/res/res/drawable-xxhdpi/stat_sys_download_anim5.png
index b495943..f5ae2eb 100644
--- a/core/res/res/drawable-xxhdpi/stat_sys_download_anim5.png
+++ b/core/res/res/drawable-xxhdpi/stat_sys_download_anim5.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_gps_on.png b/core/res/res/drawable-xxhdpi/stat_sys_gps_on.png
index 063f614..b2579c5 100644
--- a/core/res/res/drawable-xxhdpi/stat_sys_gps_on.png
+++ b/core/res/res/drawable-xxhdpi/stat_sys_gps_on.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_phone_call.png b/core/res/res/drawable-xxhdpi/stat_sys_phone_call.png
index 9348384..00933da 100644
--- a/core/res/res/drawable-xxhdpi/stat_sys_phone_call.png
+++ b/core/res/res/drawable-xxhdpi/stat_sys_phone_call.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_throttled.png b/core/res/res/drawable-xxhdpi/stat_sys_throttled.png
index c2189e4..ff46503 100644
--- a/core/res/res/drawable-xxhdpi/stat_sys_throttled.png
+++ b/core/res/res/drawable-xxhdpi/stat_sys_throttled.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_upload_anim0.png b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim0.png
index 9e63fca..e251988 100644
--- a/core/res/res/drawable-xxhdpi/stat_sys_upload_anim0.png
+++ b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim0.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_upload_anim1.png b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim1.png
index b828430..fc3f970 100644
--- a/core/res/res/drawable-xxhdpi/stat_sys_upload_anim1.png
+++ b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim1.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_upload_anim2.png b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim2.png
index 39dd3b8..c70d79c 100644
--- a/core/res/res/drawable-xxhdpi/stat_sys_upload_anim2.png
+++ b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim2.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_upload_anim3.png b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim3.png
index 7834460..78fe25c 100644
--- a/core/res/res/drawable-xxhdpi/stat_sys_upload_anim3.png
+++ b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim3.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_upload_anim4.png b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim4.png
index 34c6f27..8e3916b 100644
--- a/core/res/res/drawable-xxhdpi/stat_sys_upload_anim4.png
+++ b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim4.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_upload_anim5.png b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim5.png
index 1270acf..26aa6d8 100644
--- a/core/res/res/drawable-xxhdpi/stat_sys_upload_anim5.png
+++ b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim5.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_warning.png b/core/res/res/drawable-xxhdpi/stat_sys_warning.png
index 907de0f..f0331a1 100644
--- a/core/res/res/drawable-xxhdpi/stat_sys_warning.png
+++ b/core/res/res/drawable-xxhdpi/stat_sys_warning.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_bg_disabled_holo_dark.9.png b/core/res/res/drawable-xxhdpi/switch_bg_disabled_holo_dark.9.png
index e80453e..f0c5fdf 100644
--- a/core/res/res/drawable-xxhdpi/switch_bg_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/switch_bg_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_bg_disabled_holo_light.9.png b/core/res/res/drawable-xxhdpi/switch_bg_disabled_holo_light.9.png
index 0ec08ee..6e96029 100644
--- a/core/res/res/drawable-xxhdpi/switch_bg_disabled_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/switch_bg_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_bg_focused_holo_dark.9.png b/core/res/res/drawable-xxhdpi/switch_bg_focused_holo_dark.9.png
index 13f852d..8613b90 100644
--- a/core/res/res/drawable-xxhdpi/switch_bg_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/switch_bg_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_bg_focused_holo_light.9.png b/core/res/res/drawable-xxhdpi/switch_bg_focused_holo_light.9.png
index e7767b8..f6fdfcf 100644
--- a/core/res/res/drawable-xxhdpi/switch_bg_focused_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/switch_bg_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_bg_holo_dark.9.png b/core/res/res/drawable-xxhdpi/switch_bg_holo_dark.9.png
index d1133bf..d95c301 100644
--- a/core/res/res/drawable-xxhdpi/switch_bg_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/switch_bg_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_bg_holo_light.9.png b/core/res/res/drawable-xxhdpi/switch_bg_holo_light.9.png
index 4532035..9139404 100644
--- a/core/res/res/drawable-xxhdpi/switch_bg_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/switch_bg_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_thumb_activated_holo_dark.9.png b/core/res/res/drawable-xxhdpi/switch_thumb_activated_holo_dark.9.png
index 2b3e151..a16ba75 100644
--- a/core/res/res/drawable-xxhdpi/switch_thumb_activated_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/switch_thumb_activated_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_thumb_activated_holo_light.9.png b/core/res/res/drawable-xxhdpi/switch_thumb_activated_holo_light.9.png
index 77c08a5..a16ba75 100644
--- a/core/res/res/drawable-xxhdpi/switch_thumb_activated_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/switch_thumb_activated_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_thumb_disabled_holo_dark.9.png b/core/res/res/drawable-xxhdpi/switch_thumb_disabled_holo_dark.9.png
index 5f36c04..ba1084b 100644
--- a/core/res/res/drawable-xxhdpi/switch_thumb_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/switch_thumb_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_thumb_disabled_holo_light.9.png b/core/res/res/drawable-xxhdpi/switch_thumb_disabled_holo_light.9.png
index 7c16463..e29e862 100644
--- a/core/res/res/drawable-xxhdpi/switch_thumb_disabled_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/switch_thumb_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_thumb_holo_dark.9.png b/core/res/res/drawable-xxhdpi/switch_thumb_holo_dark.9.png
index f14f0d6..a271db6 100644
--- a/core/res/res/drawable-xxhdpi/switch_thumb_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/switch_thumb_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_thumb_holo_light.9.png b/core/res/res/drawable-xxhdpi/switch_thumb_holo_light.9.png
index 9920f54..ac9ec5b 100644
--- a/core/res/res/drawable-xxhdpi/switch_thumb_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/switch_thumb_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_thumb_holo_light_v2.9.png b/core/res/res/drawable-xxhdpi/switch_thumb_holo_light_v2.9.png
index 00518ad..508f57b 100644
--- a/core/res/res/drawable-xxhdpi/switch_thumb_holo_light_v2.9.png
+++ b/core/res/res/drawable-xxhdpi/switch_thumb_holo_light_v2.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_thumb_pressed_holo_dark.9.png b/core/res/res/drawable-xxhdpi/switch_thumb_pressed_holo_dark.9.png
index 98c517f..84f6b00 100644
--- a/core/res/res/drawable-xxhdpi/switch_thumb_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/switch_thumb_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_thumb_pressed_holo_light.9.png b/core/res/res/drawable-xxhdpi/switch_thumb_pressed_holo_light.9.png
index a93ee06..e9cf88e 100644
--- a/core/res/res/drawable-xxhdpi/switch_thumb_pressed_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/switch_thumb_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/sym_keyboard_delete.png b/core/res/res/drawable-xxhdpi/sym_keyboard_delete.png
index 9230135..17a03d1 100644
--- a/core/res/res/drawable-xxhdpi/sym_keyboard_delete.png
+++ b/core/res/res/drawable-xxhdpi/sym_keyboard_delete.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/sym_keyboard_enter.png b/core/res/res/drawable-xxhdpi/sym_keyboard_enter.png
index a234cde..2b8a468 100644
--- a/core/res/res/drawable-xxhdpi/sym_keyboard_enter.png
+++ b/core/res/res/drawable-xxhdpi/sym_keyboard_enter.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/sym_keyboard_num0_no_plus.png b/core/res/res/drawable-xxhdpi/sym_keyboard_num0_no_plus.png
index da434a4..bfb4c88 100644
--- a/core/res/res/drawable-xxhdpi/sym_keyboard_num0_no_plus.png
+++ b/core/res/res/drawable-xxhdpi/sym_keyboard_num0_no_plus.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/sym_keyboard_num1.png b/core/res/res/drawable-xxhdpi/sym_keyboard_num1.png
index 715e9aee..7f28c87 100644
--- a/core/res/res/drawable-xxhdpi/sym_keyboard_num1.png
+++ b/core/res/res/drawable-xxhdpi/sym_keyboard_num1.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/sym_keyboard_num2.png b/core/res/res/drawable-xxhdpi/sym_keyboard_num2.png
index d0cbce2..08dde55 100644
--- a/core/res/res/drawable-xxhdpi/sym_keyboard_num2.png
+++ b/core/res/res/drawable-xxhdpi/sym_keyboard_num2.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/sym_keyboard_num3.png b/core/res/res/drawable-xxhdpi/sym_keyboard_num3.png
index d152442..e90e513 100644
--- a/core/res/res/drawable-xxhdpi/sym_keyboard_num3.png
+++ b/core/res/res/drawable-xxhdpi/sym_keyboard_num3.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/sym_keyboard_num4.png b/core/res/res/drawable-xxhdpi/sym_keyboard_num4.png
index 9438f47..ccd4c1c 100644
--- a/core/res/res/drawable-xxhdpi/sym_keyboard_num4.png
+++ b/core/res/res/drawable-xxhdpi/sym_keyboard_num4.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/sym_keyboard_num5.png b/core/res/res/drawable-xxhdpi/sym_keyboard_num5.png
index 0104cfe..1ecee75 100644
--- a/core/res/res/drawable-xxhdpi/sym_keyboard_num5.png
+++ b/core/res/res/drawable-xxhdpi/sym_keyboard_num5.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/sym_keyboard_num6.png b/core/res/res/drawable-xxhdpi/sym_keyboard_num6.png
index 852d0a22..be681cf 100644
--- a/core/res/res/drawable-xxhdpi/sym_keyboard_num6.png
+++ b/core/res/res/drawable-xxhdpi/sym_keyboard_num6.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/sym_keyboard_num7.png b/core/res/res/drawable-xxhdpi/sym_keyboard_num7.png
index bdd1e22..6a7c41c 100644
--- a/core/res/res/drawable-xxhdpi/sym_keyboard_num7.png
+++ b/core/res/res/drawable-xxhdpi/sym_keyboard_num7.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/sym_keyboard_num8.png b/core/res/res/drawable-xxhdpi/sym_keyboard_num8.png
index 0d9a0f3..fa6225e 100644
--- a/core/res/res/drawable-xxhdpi/sym_keyboard_num8.png
+++ b/core/res/res/drawable-xxhdpi/sym_keyboard_num8.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/sym_keyboard_num9.png b/core/res/res/drawable-xxhdpi/sym_keyboard_num9.png
index ab87892..2823250 100644
--- a/core/res/res/drawable-xxhdpi/sym_keyboard_num9.png
+++ b/core/res/res/drawable-xxhdpi/sym_keyboard_num9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/sym_keyboard_return_holo.png b/core/res/res/drawable-xxhdpi/sym_keyboard_return_holo.png
index 7d95807..364feae 100644
--- a/core/res/res/drawable-xxhdpi/sym_keyboard_return_holo.png
+++ b/core/res/res/drawable-xxhdpi/sym_keyboard_return_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/tab_indicator_mtrl_alpha.9.png b/core/res/res/drawable-xxhdpi/tab_indicator_mtrl_alpha.9.png
index 248f4f8..c148615 100644
--- a/core/res/res/drawable-xxhdpi/tab_indicator_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xxhdpi/tab_indicator_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/tab_selected_focused_holo.9.png b/core/res/res/drawable-xxhdpi/tab_selected_focused_holo.9.png
index 619efa4..0cc577d 100644
--- a/core/res/res/drawable-xxhdpi/tab_selected_focused_holo.9.png
+++ b/core/res/res/drawable-xxhdpi/tab_selected_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/tab_selected_holo.9.png b/core/res/res/drawable-xxhdpi/tab_selected_holo.9.png
index bee35ca..b7e9f68 100644
--- a/core/res/res/drawable-xxhdpi/tab_selected_holo.9.png
+++ b/core/res/res/drawable-xxhdpi/tab_selected_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/tab_selected_pressed_holo.9.png b/core/res/res/drawable-xxhdpi/tab_selected_pressed_holo.9.png
index ffedd02..f3b6f29 100644
--- a/core/res/res/drawable-xxhdpi/tab_selected_pressed_holo.9.png
+++ b/core/res/res/drawable-xxhdpi/tab_selected_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/tab_unselected_focused_holo.9.png b/core/res/res/drawable-xxhdpi/tab_unselected_focused_holo.9.png
index e9a5bf5..6639a68 100644
--- a/core/res/res/drawable-xxhdpi/tab_unselected_focused_holo.9.png
+++ b/core/res/res/drawable-xxhdpi/tab_unselected_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/tab_unselected_holo.9.png b/core/res/res/drawable-xxhdpi/tab_unselected_holo.9.png
index 8fcecf7..eb72c5f 100644
--- a/core/res/res/drawable-xxhdpi/tab_unselected_holo.9.png
+++ b/core/res/res/drawable-xxhdpi/tab_unselected_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/tab_unselected_pressed_holo.9.png b/core/res/res/drawable-xxhdpi/tab_unselected_pressed_holo.9.png
index 82c6998..f30f73a 100644
--- a/core/res/res/drawable-xxhdpi/tab_unselected_pressed_holo.9.png
+++ b/core/res/res/drawable-xxhdpi/tab_unselected_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/text_edit_paste_window.9.png b/core/res/res/drawable-xxhdpi/text_edit_paste_window.9.png
index 9e247e6..b181e42 100644
--- a/core/res/res/drawable-xxhdpi/text_edit_paste_window.9.png
+++ b/core/res/res/drawable-xxhdpi/text_edit_paste_window.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/text_edit_suggestions_window.9.png b/core/res/res/drawable-xxhdpi/text_edit_suggestions_window.9.png
index 9e247e6..b181e42 100644
--- a/core/res/res/drawable-xxhdpi/text_edit_suggestions_window.9.png
+++ b/core/res/res/drawable-xxhdpi/text_edit_suggestions_window.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/text_select_handle_left_mtrl_alpha.png b/core/res/res/drawable-xxhdpi/text_select_handle_left_mtrl_alpha.png
index f0e32af..df196a2 100644
--- a/core/res/res/drawable-xxhdpi/text_select_handle_left_mtrl_alpha.png
+++ b/core/res/res/drawable-xxhdpi/text_select_handle_left_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/text_select_handle_middle_mtrl_alpha.png b/core/res/res/drawable-xxhdpi/text_select_handle_middle_mtrl_alpha.png
index 5753d89..532ba83 100644
--- a/core/res/res/drawable-xxhdpi/text_select_handle_middle_mtrl_alpha.png
+++ b/core/res/res/drawable-xxhdpi/text_select_handle_middle_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/text_select_handle_right_mtrl_alpha.png b/core/res/res/drawable-xxhdpi/text_select_handle_right_mtrl_alpha.png
index 260e090..a561684 100644
--- a/core/res/res/drawable-xxhdpi/text_select_handle_right_mtrl_alpha.png
+++ b/core/res/res/drawable-xxhdpi/text_select_handle_right_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_activated_holo_dark.9.png b/core/res/res/drawable-xxhdpi/textfield_activated_holo_dark.9.png
index a4c891e..c65b075 100644
--- a/core/res/res/drawable-xxhdpi/textfield_activated_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/textfield_activated_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_activated_holo_light.9.png b/core/res/res/drawable-xxhdpi/textfield_activated_holo_light.9.png
index a4c891e..c65b075 100644
--- a/core/res/res/drawable-xxhdpi/textfield_activated_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/textfield_activated_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_activated_mtrl_alpha.9.png b/core/res/res/drawable-xxhdpi/textfield_activated_mtrl_alpha.9.png
index 778670a..78cedb5 100644
--- a/core/res/res/drawable-xxhdpi/textfield_activated_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xxhdpi/textfield_activated_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_default_holo_dark.9.png b/core/res/res/drawable-xxhdpi/textfield_default_holo_dark.9.png
index 1e8dafa..5ca09b7 100644
--- a/core/res/res/drawable-xxhdpi/textfield_default_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/textfield_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_default_holo_light.9.png b/core/res/res/drawable-xxhdpi/textfield_default_holo_light.9.png
index 9ece814..d249acb 100644
--- a/core/res/res/drawable-xxhdpi/textfield_default_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/textfield_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_default_mtrl_alpha.9.png b/core/res/res/drawable-xxhdpi/textfield_default_mtrl_alpha.9.png
index 6dd5d4f..95d1174 100644
--- a/core/res/res/drawable-xxhdpi/textfield_default_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xxhdpi/textfield_default_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_disabled_focused_holo_dark.9.png b/core/res/res/drawable-xxhdpi/textfield_disabled_focused_holo_dark.9.png
index e21548e..db27a9b 100644
--- a/core/res/res/drawable-xxhdpi/textfield_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/textfield_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_disabled_focused_holo_light.9.png b/core/res/res/drawable-xxhdpi/textfield_disabled_focused_holo_light.9.png
index 5bc20f9..a503a35 100644
--- a/core/res/res/drawable-xxhdpi/textfield_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/textfield_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_disabled_holo_dark.9.png b/core/res/res/drawable-xxhdpi/textfield_disabled_holo_dark.9.png
index 5592f76..de4964c 100644
--- a/core/res/res/drawable-xxhdpi/textfield_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/textfield_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_disabled_holo_light.9.png b/core/res/res/drawable-xxhdpi/textfield_disabled_holo_light.9.png
index 8fda94d..dbfc17b 100644
--- a/core/res/res/drawable-xxhdpi/textfield_disabled_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/textfield_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_focused_holo_dark.9.png b/core/res/res/drawable-xxhdpi/textfield_focused_holo_dark.9.png
index d557164..5ac68d6 100644
--- a/core/res/res/drawable-xxhdpi/textfield_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/textfield_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_focused_holo_light.9.png b/core/res/res/drawable-xxhdpi/textfield_focused_holo_light.9.png
index d557164..5ac68d6 100644
--- a/core/res/res/drawable-xxhdpi/textfield_focused_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/textfield_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_multiline_activated_holo_dark.9.png b/core/res/res/drawable-xxhdpi/textfield_multiline_activated_holo_dark.9.png
index a4c891e..c65b075 100644
--- a/core/res/res/drawable-xxhdpi/textfield_multiline_activated_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/textfield_multiline_activated_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_multiline_activated_holo_light.9.png b/core/res/res/drawable-xxhdpi/textfield_multiline_activated_holo_light.9.png
index a4c891e..c65b075 100644
--- a/core/res/res/drawable-xxhdpi/textfield_multiline_activated_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/textfield_multiline_activated_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_multiline_default_holo_dark.9.png b/core/res/res/drawable-xxhdpi/textfield_multiline_default_holo_dark.9.png
index 1e8dafa..5ca09b7 100644
--- a/core/res/res/drawable-xxhdpi/textfield_multiline_default_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/textfield_multiline_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_multiline_default_holo_light.9.png b/core/res/res/drawable-xxhdpi/textfield_multiline_default_holo_light.9.png
index 9ece814..d249acb 100644
--- a/core/res/res/drawable-xxhdpi/textfield_multiline_default_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/textfield_multiline_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_multiline_disabled_focused_holo_dark.9.png b/core/res/res/drawable-xxhdpi/textfield_multiline_disabled_focused_holo_dark.9.png
index e21548e..db27a9b 100644
--- a/core/res/res/drawable-xxhdpi/textfield_multiline_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/textfield_multiline_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_multiline_disabled_focused_holo_light.9.png b/core/res/res/drawable-xxhdpi/textfield_multiline_disabled_focused_holo_light.9.png
index 5bc20f9..a503a35 100644
--- a/core/res/res/drawable-xxhdpi/textfield_multiline_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/textfield_multiline_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_multiline_disabled_holo_dark.9.png b/core/res/res/drawable-xxhdpi/textfield_multiline_disabled_holo_dark.9.png
index 5592f76..de4964c 100644
--- a/core/res/res/drawable-xxhdpi/textfield_multiline_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/textfield_multiline_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_multiline_disabled_holo_light.9.png b/core/res/res/drawable-xxhdpi/textfield_multiline_disabled_holo_light.9.png
index 8fda94d..dbfc17b 100644
--- a/core/res/res/drawable-xxhdpi/textfield_multiline_disabled_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/textfield_multiline_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_multiline_focused_holo_dark.9.png b/core/res/res/drawable-xxhdpi/textfield_multiline_focused_holo_dark.9.png
index d557164..5ac68d6 100644
--- a/core/res/res/drawable-xxhdpi/textfield_multiline_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/textfield_multiline_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_multiline_focused_holo_light.9.png b/core/res/res/drawable-xxhdpi/textfield_multiline_focused_holo_light.9.png
index d557164..5ac68d6 100644
--- a/core/res/res/drawable-xxhdpi/textfield_multiline_focused_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/textfield_multiline_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_search_activated_mtrl_alpha.9.png b/core/res/res/drawable-xxhdpi/textfield_search_activated_mtrl_alpha.9.png
index b6efff3..1b042f1 100644
--- a/core/res/res/drawable-xxhdpi/textfield_search_activated_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xxhdpi/textfield_search_activated_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_search_default_holo_dark.9.png b/core/res/res/drawable-xxhdpi/textfield_search_default_holo_dark.9.png
index e634c75..a94baa4 100644
--- a/core/res/res/drawable-xxhdpi/textfield_search_default_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/textfield_search_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_search_default_holo_light.9.png b/core/res/res/drawable-xxhdpi/textfield_search_default_holo_light.9.png
index ea9dd89..1a16b55 100644
--- a/core/res/res/drawable-xxhdpi/textfield_search_default_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/textfield_search_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_search_default_mtrl_alpha.9.png b/core/res/res/drawable-xxhdpi/textfield_search_default_mtrl_alpha.9.png
index 2b253fb..d4f36506 100644
--- a/core/res/res/drawable-xxhdpi/textfield_search_default_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xxhdpi/textfield_search_default_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_search_right_default_holo_dark.9.png b/core/res/res/drawable-xxhdpi/textfield_search_right_default_holo_dark.9.png
index 6042bcf..37c5424 100644
--- a/core/res/res/drawable-xxhdpi/textfield_search_right_default_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/textfield_search_right_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_search_right_default_holo_light.9.png b/core/res/res/drawable-xxhdpi/textfield_search_right_default_holo_light.9.png
index b34b536..f3ba716 100644
--- a/core/res/res/drawable-xxhdpi/textfield_search_right_default_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/textfield_search_right_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_search_right_selected_holo_dark.9.png b/core/res/res/drawable-xxhdpi/textfield_search_right_selected_holo_dark.9.png
index 114acf4..3c4fcab 100644
--- a/core/res/res/drawable-xxhdpi/textfield_search_right_selected_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/textfield_search_right_selected_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_search_right_selected_holo_light.9.png b/core/res/res/drawable-xxhdpi/textfield_search_right_selected_holo_light.9.png
index 098475b..6aa6e74 100644
--- a/core/res/res/drawable-xxhdpi/textfield_search_right_selected_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/textfield_search_right_selected_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_search_selected_holo_dark.9.png b/core/res/res/drawable-xxhdpi/textfield_search_selected_holo_dark.9.png
index 8fcaadc..fd55312 100644
--- a/core/res/res/drawable-xxhdpi/textfield_search_selected_holo_dark.9.png
+++ b/core/res/res/drawable-xxhdpi/textfield_search_selected_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_search_selected_holo_light.9.png b/core/res/res/drawable-xxhdpi/textfield_search_selected_holo_light.9.png
index df5c730..3a457a2 100644
--- a/core/res/res/drawable-xxhdpi/textfield_search_selected_holo_light.9.png
+++ b/core/res/res/drawable-xxhdpi/textfield_search_selected_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/transportcontrol_bg.9.png b/core/res/res/drawable-xxhdpi/transportcontrol_bg.9.png
index a5dc6cb..39c5aad 100644
--- a/core/res/res/drawable-xxhdpi/transportcontrol_bg.9.png
+++ b/core/res/res/drawable-xxhdpi/transportcontrol_bg.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_14w.png b/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_14w.png
index c0d72d7..8a00760 100644
--- a/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_14w.png
+++ b/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_14w.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_15w.png b/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_15w.png
index d7c0ec0..64a0cab 100644
--- a/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_15w.png
+++ b/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_15w.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_16w.png b/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_16w.png
index 5815ba9..ce7369e 100644
--- a/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_16w.png
+++ b/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_16w.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_17w.png b/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_17w.png
index 41da8c0..398e3f2 100644
--- a/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_17w.png
+++ b/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_17w.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_18w.png b/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_18w.png
index 975eb01..1cf40e2 100644
--- a/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_18w.png
+++ b/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_18w.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/watch_switch_track_mtrl.png b/core/res/res/drawable-xxhdpi/watch_switch_track_mtrl.png
index af2042b..9450546 100644
--- a/core/res/res/drawable-xxhdpi/watch_switch_track_mtrl.png
+++ b/core/res/res/drawable-xxhdpi/watch_switch_track_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00001.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00001.9.png
index 786f493..ae66e3d 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00001.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00002.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00002.9.png
index c6e1ac1f..5bdb581 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00002.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00003.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00003.9.png
index 2a65baa..99b4905 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00003.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00004.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00004.9.png
index efce521..5224d9a 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00004.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00005.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00005.9.png
index 5566524..cc2d46b 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00005.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00006.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00006.9.png
index ee676a6..8973dce9 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00006.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00007.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00007.9.png
index e0bb175..0d1bf80 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00007.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00008.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00008.9.png
index de9eadae..f923224 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00008.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00009.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00009.9.png
index 3c59ad8..32c13f1 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00009.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00010.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00010.9.png
index d524098..b3ba1de 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00010.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00011.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00011.9.png
index 7c08d71..0a4a927 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00011.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00012.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00012.9.png
index 017c2e1..830ee25 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00012.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00001.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00001.9.png
index d3f2a9a..4e9f875 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00001.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00002.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00002.9.png
index cb75295a..49e6ff5 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00002.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00003.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00003.9.png
index 445644e..5b26155 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00003.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00004.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00004.9.png
index 5819f90..9e5c3bf 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00004.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00005.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00005.9.png
index 91cb90f..a781e78 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00005.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00006.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00006.9.png
index cf6147c..6ea0492 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00006.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00007.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00007.9.png
index 75fca7c..0d1bf80 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00007.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00008.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00008.9.png
index b71a0b4..288c7b7 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00008.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00009.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00009.9.png
index edb7671..52ea600 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00009.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00010.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00010.9.png
index 5e0be17..e256788 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00010.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00011.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00011.9.png
index b727eda..be132d2 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00011.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00012.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00012.9.png
index a3caefb..0dc4205 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00012.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/ic_launcher_android.png b/core/res/res/drawable-xxxhdpi/ic_launcher_android.png
index eedc9f9..0df77cf 100644
--- a/core/res/res/drawable-xxxhdpi/ic_launcher_android.png
+++ b/core/res/res/drawable-xxxhdpi/ic_launcher_android.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/ic_lock_open_wht_24dp.png b/core/res/res/drawable-xxxhdpi/ic_lock_open_wht_24dp.png
index 8774412..609c9e5 100644
--- a/core/res/res/drawable-xxxhdpi/ic_lock_open_wht_24dp.png
+++ b/core/res/res/drawable-xxxhdpi/ic_lock_open_wht_24dp.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/ic_lock_outline_wht_24dp.png b/core/res/res/drawable-xxxhdpi/ic_lock_outline_wht_24dp.png
index 1375acc..d2bdf81 100644
--- a/core/res/res/drawable-xxxhdpi/ic_lock_outline_wht_24dp.png
+++ b/core/res/res/drawable-xxxhdpi/ic_lock_outline_wht_24dp.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/ic_menu_search_mtrl_alpha.png b/core/res/res/drawable-xxxhdpi/ic_menu_search_mtrl_alpha.png
index 2a28f0f..83d7714 100644
--- a/core/res/res/drawable-xxxhdpi/ic_menu_search_mtrl_alpha.png
+++ b/core/res/res/drawable-xxxhdpi/ic_menu_search_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/ic_sim_card_multi_24px_clr.png b/core/res/res/drawable-xxxhdpi/ic_sim_card_multi_24px_clr.png
index fbda037..f80213b 100644
--- a/core/res/res/drawable-xxxhdpi/ic_sim_card_multi_24px_clr.png
+++ b/core/res/res/drawable-xxxhdpi/ic_sim_card_multi_24px_clr.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/ic_sim_card_multi_48px_clr.png b/core/res/res/drawable-xxxhdpi/ic_sim_card_multi_48px_clr.png
index 3316f14..70946da 100644
--- a/core/res/res/drawable-xxxhdpi/ic_sim_card_multi_48px_clr.png
+++ b/core/res/res/drawable-xxxhdpi/ic_sim_card_multi_48px_clr.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/ic_star_half_black_16dp.png b/core/res/res/drawable-xxxhdpi/ic_star_half_black_16dp.png
index 266c167..0a793ec 100644
--- a/core/res/res/drawable-xxxhdpi/ic_star_half_black_16dp.png
+++ b/core/res/res/drawable-xxxhdpi/ic_star_half_black_16dp.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/ic_star_half_black_36dp.png b/core/res/res/drawable-xxxhdpi/ic_star_half_black_36dp.png
index debdb77..fa5b801 100644
--- a/core/res/res/drawable-xxxhdpi/ic_star_half_black_36dp.png
+++ b/core/res/res/drawable-xxxhdpi/ic_star_half_black_36dp.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/ic_star_half_black_48dp.png b/core/res/res/drawable-xxxhdpi/ic_star_half_black_48dp.png
index bfb6e61..29716c5 100644
--- a/core/res/res/drawable-xxxhdpi/ic_star_half_black_48dp.png
+++ b/core/res/res/drawable-xxxhdpi/ic_star_half_black_48dp.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/perm_group_accessibility_features.png b/core/res/res/drawable-xxxhdpi/perm_group_accessibility_features.png
index 8cebecf..86fc9464 100644
--- a/core/res/res/drawable-xxxhdpi/perm_group_accessibility_features.png
+++ b/core/res/res/drawable-xxxhdpi/perm_group_accessibility_features.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/perm_group_affects_battery.png b/core/res/res/drawable-xxxhdpi/perm_group_affects_battery.png
index 3b6300a..2e9e06f 100644
--- a/core/res/res/drawable-xxxhdpi/perm_group_affects_battery.png
+++ b/core/res/res/drawable-xxxhdpi/perm_group_affects_battery.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/perm_group_app_info.png b/core/res/res/drawable-xxxhdpi/perm_group_app_info.png
index b54b98a..e0ec029 100644
--- a/core/res/res/drawable-xxxhdpi/perm_group_app_info.png
+++ b/core/res/res/drawable-xxxhdpi/perm_group_app_info.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/perm_group_audio_settings.png b/core/res/res/drawable-xxxhdpi/perm_group_audio_settings.png
index ec88cdd1..cf42b66 100644
--- a/core/res/res/drawable-xxxhdpi/perm_group_audio_settings.png
+++ b/core/res/res/drawable-xxxhdpi/perm_group_audio_settings.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/perm_group_bluetooth.png b/core/res/res/drawable-xxxhdpi/perm_group_bluetooth.png
index 6f6409d..62b3389 100644
--- a/core/res/res/drawable-xxxhdpi/perm_group_bluetooth.png
+++ b/core/res/res/drawable-xxxhdpi/perm_group_bluetooth.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/perm_group_bookmarks.png b/core/res/res/drawable-xxxhdpi/perm_group_bookmarks.png
index f8f3f44..5806aad 100644
--- a/core/res/res/drawable-xxxhdpi/perm_group_bookmarks.png
+++ b/core/res/res/drawable-xxxhdpi/perm_group_bookmarks.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/perm_group_device_alarms.png b/core/res/res/drawable-xxxhdpi/perm_group_device_alarms.png
index 00707d4..ec4393a 100644
--- a/core/res/res/drawable-xxxhdpi/perm_group_device_alarms.png
+++ b/core/res/res/drawable-xxxhdpi/perm_group_device_alarms.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/perm_group_display.png b/core/res/res/drawable-xxxhdpi/perm_group_display.png
index ca4f44b..325ee7c 100644
--- a/core/res/res/drawable-xxxhdpi/perm_group_display.png
+++ b/core/res/res/drawable-xxxhdpi/perm_group_display.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/perm_group_network.png b/core/res/res/drawable-xxxhdpi/perm_group_network.png
index 07f1eb7..91cb227 100644
--- a/core/res/res/drawable-xxxhdpi/perm_group_network.png
+++ b/core/res/res/drawable-xxxhdpi/perm_group_network.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/perm_group_personal_info.png b/core/res/res/drawable-xxxhdpi/perm_group_personal_info.png
index 11eb453..d6a1d2f 100644
--- a/core/res/res/drawable-xxxhdpi/perm_group_personal_info.png
+++ b/core/res/res/drawable-xxxhdpi/perm_group_personal_info.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/perm_group_screenlock.png b/core/res/res/drawable-xxxhdpi/perm_group_screenlock.png
index d559dce..a74cde1 100644
--- a/core/res/res/drawable-xxxhdpi/perm_group_screenlock.png
+++ b/core/res/res/drawable-xxxhdpi/perm_group_screenlock.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/perm_group_shortrange_network.png b/core/res/res/drawable-xxxhdpi/perm_group_shortrange_network.png
index 3998ab6..475027a 100644
--- a/core/res/res/drawable-xxxhdpi/perm_group_shortrange_network.png
+++ b/core/res/res/drawable-xxxhdpi/perm_group_shortrange_network.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/perm_group_status_bar.png b/core/res/res/drawable-xxxhdpi/perm_group_status_bar.png
index 1b02702..df50ff3 100644
--- a/core/res/res/drawable-xxxhdpi/perm_group_status_bar.png
+++ b/core/res/res/drawable-xxxhdpi/perm_group_status_bar.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/perm_group_sync_settings.png b/core/res/res/drawable-xxxhdpi/perm_group_sync_settings.png
index 12f90c5..277cd1a 100644
--- a/core/res/res/drawable-xxxhdpi/perm_group_sync_settings.png
+++ b/core/res/res/drawable-xxxhdpi/perm_group_sync_settings.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/perm_group_system_clock.png b/core/res/res/drawable-xxxhdpi/perm_group_system_clock.png
index afd968b..3d88464 100644
--- a/core/res/res/drawable-xxxhdpi/perm_group_system_clock.png
+++ b/core/res/res/drawable-xxxhdpi/perm_group_system_clock.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/perm_group_system_tools.png b/core/res/res/drawable-xxxhdpi/perm_group_system_tools.png
index dfcb702..e3fc1fa 100644
--- a/core/res/res/drawable-xxxhdpi/perm_group_system_tools.png
+++ b/core/res/res/drawable-xxxhdpi/perm_group_system_tools.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/perm_group_voicemail.png b/core/res/res/drawable-xxxhdpi/perm_group_voicemail.png
index 7aeb786..11abfcd 100644
--- a/core/res/res/drawable-xxxhdpi/perm_group_voicemail.png
+++ b/core/res/res/drawable-xxxhdpi/perm_group_voicemail.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/perm_group_wallpaper.png b/core/res/res/drawable-xxxhdpi/perm_group_wallpaper.png
index 3c08471..5f8f4c6 100644
--- a/core/res/res/drawable-xxxhdpi/perm_group_wallpaper.png
+++ b/core/res/res/drawable-xxxhdpi/perm_group_wallpaper.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/tab_indicator_mtrl_alpha.9.png b/core/res/res/drawable-xxxhdpi/tab_indicator_mtrl_alpha.9.png
index 5813179..fc79b7e 100644
--- a/core/res/res/drawable-xxxhdpi/tab_indicator_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xxxhdpi/tab_indicator_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/text_select_handle_left_mtrl_alpha.png b/core/res/res/drawable-xxxhdpi/text_select_handle_left_mtrl_alpha.png
index a7a48b8..3e7026b 100644
--- a/core/res/res/drawable-xxxhdpi/text_select_handle_left_mtrl_alpha.png
+++ b/core/res/res/drawable-xxxhdpi/text_select_handle_left_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/text_select_handle_right_mtrl_alpha.png b/core/res/res/drawable-xxxhdpi/text_select_handle_right_mtrl_alpha.png
index 2c72f4f..b12b73b 100644
--- a/core/res/res/drawable-xxxhdpi/text_select_handle_right_mtrl_alpha.png
+++ b/core/res/res/drawable-xxxhdpi/text_select_handle_right_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable/work_mode_emergency_button_background.xml b/core/res/res/drawable/work_mode_emergency_button_background.xml
new file mode 100644
index 0000000..d9b6879
--- /dev/null
+++ b/core/res/res/drawable/work_mode_emergency_button_background.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ android:insetTop="6dp"
+ android:insetBottom="6dp">
+ <shape android:shape="rectangle">
+ <corners android:radius="18dp"/>
+ <solid android:color="@android:color/system_accent3_100" />
+ </shape>
+</inset>
\ No newline at end of file
diff --git a/core/res/res/layout/autofill_fill_dialog.xml b/core/res/res/layout/autofill_fill_dialog.xml
index c382a65..2e65800 100644
--- a/core/res/res/layout/autofill_fill_dialog.xml
+++ b/core/res/res/layout/autofill_fill_dialog.xml
@@ -93,7 +93,7 @@
android:layout_height="36dp"
android:layout_marginTop="6dp"
android:layout_marginBottom="6dp"
- style="@style/AutofillHalfSheetOutlinedButton"
+ style="?android:attr/borderlessButtonStyle"
android:text="@string/autofill_save_no">
</Button>
diff --git a/core/res/res/layout/autofill_save.xml b/core/res/res/layout/autofill_save.xml
index fd08241..3c0b789 100644
--- a/core/res/res/layout/autofill_save.xml
+++ b/core/res/res/layout/autofill_save.xml
@@ -81,7 +81,7 @@
android:layout_height="36dp"
android:layout_marginTop="6dp"
android:layout_marginBottom="6dp"
- style="@style/AutofillHalfSheetOutlinedButton"
+ style="?android:attr/borderlessButtonStyle"
android:text="@string/autofill_save_no">
</Button>
diff --git a/core/res/res/values-television/themes_device_defaults.xml b/core/res/res/values-television/themes_device_defaults.xml
index 9d0e522..7cda99a 100644
--- a/core/res/res/values-television/themes_device_defaults.xml
+++ b/core/res/res/values-television/themes_device_defaults.xml
@@ -14,6 +14,7 @@
limitations under the License.
-->
<resources>
+ <style name="Theme.DeviceDefault.Dialog" parent="Theme.Leanback.Dialog" />
<style name="Theme.DeviceDefault.Dialog.Alert" parent="Theme.Leanback.Dialog.Alert" />
<style name="Theme.DeviceDefault.Dialog.AppError" parent="Theme.Leanback.Dialog.AppError" />
<style name="Theme.DeviceDefault.Light.Dialog.Alert" parent="Theme.Leanback.Dialog.Alert" />
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 1d1c02d..1b6f88f 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2653,6 +2653,10 @@
<flag name="noExcludeDescendants" value="0x8" />
</attr>
+ <!-- Boolean that hints the Android System that the view is credntial and associated with
+ CredentialManager -->
+ <attr name="isCredential" format="boolean" />
+
<!-- Hints the Android System whether the this View should be considered a scroll capture target. -->
<attr name="scrollCaptureHint">
<!-- Let the Android System determine if the view can be a scroll capture target. -->
@@ -5134,6 +5138,15 @@
<attr name="textLocale" format="string" />
<!-- Color of the text selection highlight. -->
<attr name="textColorHighlight" />
+ <!-- Color of search results highlight.
+ This color is typically used when TextView/EditText shows search result in-app text
+ search invoked with Ctrl+F. -->
+ <attr name="searchResultHighlightColor" format="color" />
+ <!-- Color of focused search result highlight.
+ This color is typically used when TextView/EditText shows search result in-app text
+ search invoked with Ctrl+F. -->
+ <attr name="focusedSearchResultHighlightColor" format="color" />
+
<!-- Color of the hint text. -->
<attr name="textColorHint" />
<!-- Color of the links. -->
@@ -5211,6 +5224,14 @@
<attr name="textColor" />
<!-- Color of the text selection highlight. -->
<attr name="textColorHighlight" />
+ <!-- Color of search results highlight.
+ This color is typically used when TextView/EditText shows search result in-app text
+ search invoked with Ctrl+F. -->
+ <attr name="searchResultHighlightColor" format="color" />
+ <!-- Color of focused search result highlight.
+ This color is typically used when TextView/EditText shows search result in-app text
+ search invoked with Ctrl+F. -->
+ <attr name="focusedSearchResultHighlightColor" format="color" />
<!-- Color of the hint text. -->
<attr name="textColorHint" />
<!-- Base text color, typeface, size, and style. -->
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 8ac13ef..ef94484 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1783,6 +1783,14 @@
-->
<attr name="attributionTags" format="string" />
+ <!-- Default value <code>true</code> allows an installer to enable update
+ ownership enforcement for this package via {@link
+ android.content.pm.PackageInstaller.SessionParams#setRequestUpdateOwnership}
+ during initial installation. This overrides the installer's use of {@link
+ android.content.pm.PackageInstaller.SessionParams#setRequestUpdateOwnership}.
+ -->
+ <attr name="allowUpdateOwnership" format="boolean" />
+
<!-- The <code>manifest</code> tag is the root of an
<code>AndroidManifest.xml</code> file,
describing the contents of an Android package (.apk) file. One
@@ -1820,6 +1828,7 @@
<attr name="isSplitRequired" />
<attr name="requiredSplitTypes" />
<attr name="splitTypes" />
+ <attr name="allowUpdateOwnership" />
</declare-styleable>
<!-- The <code>application</code> tag describes application-level components
diff --git a/core/res/res/values/public-staging.xml b/core/res/res/values/public-staging.xml
index dfd4d9a..f4b49e6 100644
--- a/core/res/res/values/public-staging.xml
+++ b/core/res/res/values/public-staging.xml
@@ -124,6 +124,10 @@
<public name="allowSharedIsolatedProcess" />
<public name="keyboardLocale" />
<public name="keyboardLayoutType" />
+ <public name="allowUpdateOwnership" />
+ <public name="isCredential"/>
+ <public name="searchResultHighlightColor" />
+ <public name="focusedSearchResultHighlightColor" />
</staging-public-group>
<staging-public-group type="id" first-id="0x01cd0000">
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index b754440..7c6f81d 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -5329,6 +5329,10 @@
<string name="work_mode_off_message">Get access to your work apps and notifications</string>
<!-- Title for button to turn on work profile. [CHAR LIMIT=NONE] -->
<string name="work_mode_turn_on">Turn on</string>
+ <!-- Title for button to launch the personal safety app to make an emergency call -->
+ <string name="work_mode_emergency_call_button">Emergency</string>
+ <!-- Text shown in a dialog when the user tries to launch a disabled work profile app when work apps are paused-->
+ <string name="work_mode_dialer_off_message">Get access to your work apps and calls</string>
<!-- Title of the dialog that is shown when the user tries to launch a blocked application [CHAR LIMIT=50] -->
<string name="app_blocked_title">App is not available</string>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 476c18e..0a7ffca 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -30,7 +30,7 @@
-->
<resources>
<!-- Global Theme Styles -->
- <eat-comment />
+ <eat-comment/>
<style name="WindowTitleBackground">
<item name="background">@drawable/title_bar</item>
@@ -69,6 +69,19 @@
<item name="needsDefaultBackgrounds">false</item>
</style>
+ <!-- Base style for the alert dialog with emergency call button -->
+ <style name="AlertDialogWithEmergencyButton" parent="AlertDialog">
+ <item name="buttonBarNeutralButtonStyle">@style/AlertDialogEmergencyButtonStyle</item>
+ </style>
+
+ <style name="AlertDialogEmergencyButtonStyle" parent="AlertDialogWithEmergencyButton">
+ <item name="background">@drawable/work_mode_emergency_button_background</item>
+ <item name="textColor">@color/text_color_on_accent_device_default</item>
+ <item name="paddingLeft">15dip</item>
+ <item name="paddingRight">15dip</item>
+ <item name="layout_marginStart">10dip</item>
+ </style>
+
<style name="Widget.PreferenceFrameLayout">
<item name="borderTop">0dip</item>
<item name="borderBottom">0dip</item>
@@ -77,7 +90,7 @@
</style>
<!-- Base style for animations. This style specifies no animations. -->
- <style name="Animation" />
+ <style name="Animation"/>
<!-- Standard animations for a full-screen window or activity. -->
<style name="Animation.Activity">
@@ -231,7 +244,7 @@
</style>
<!-- A special animation value used internally for popup windows. -->
- <style name="Animation.PopupWindow" />
+ <style name="Animation.PopupWindow"/>
<!-- Window animations used for action mode UI in overlay mode. -->
<style name="Animation.PopupWindow.ActionMode">
@@ -503,7 +516,8 @@
<item name="textEditSidePasteWindowLayout">?attr/textEditSidePasteWindowLayout</item>
<item name="textEditSideNoPasteWindowLayout">?attr/textEditSideNoPasteWindowLayout</item>
<item name="textEditSuggestionItemLayout">?attr/textEditSuggestionItemLayout</item>
- <item name="textEditSuggestionContainerLayout">?attr/textEditSuggestionContainerLayout</item>
+ <item name="textEditSuggestionContainerLayout">?attr/textEditSuggestionContainerLayout
+ </item>
<item name="textEditSuggestionHighlightStyle">?attr/textEditSuggestionHighlightStyle</item>
<item name="textCursorDrawable">?attr/textCursorDrawable</item>
<item name="breakStrategy">high_quality</item>
@@ -593,7 +607,8 @@
<item name="weekNumberColor">#33FFFFFF</item>
<item name="weekSeparatorLineColor">#19FFFFFF</item>
<item name="selectedDateVerticalBar">@drawable/day_picker_week_view_dayline_holo</item>
- <item name="weekDayTextAppearance">@style/TextAppearance.Small.CalendarViewWeekDayView</item>
+ <item name="weekDayTextAppearance">@style/TextAppearance.Small.CalendarViewWeekDayView
+ </item>
<item name="dateTextAppearance">?attr/textAppearanceSmall</item>
<item name="calendarViewMode">holo</item>
</style>
@@ -689,12 +704,12 @@
</style>
<style name="Widget.ListView.DropDown">
- <item name="cacheColorHint">@null</item>
+ <item name="cacheColorHint">@null</item>
<item name="divider">@drawable/divider_horizontal_bright_opaque</item>
</style>
<style name="Widget.ListView.Menu" parent="Widget.Holo.ListView">
- <item name="cacheColorHint">@null</item>
+ <item name="cacheColorHint">@null</item>
<item name="scrollbars">vertical</item>
<item name="fadingEdge">none</item>
<!-- Light background for the list in menus, so the divider for bright themes -->
@@ -819,7 +834,7 @@
</style>
<!-- Text Appearances -->
- <eat-comment />
+ <eat-comment/>
<style name="TextAppearance">
<item name="textColor">?textColorPrimary</item>
@@ -878,9 +893,9 @@
<item name="textColorLink">?textColorLinkInverse</item>
</style>
- <style name="TextAppearance.Theme.Dialog" parent="TextAppearance.Theme" />
+ <style name="TextAppearance.Theme.Dialog" parent="TextAppearance.Theme"/>
- <style name="TextAppearance.Widget" />
+ <style name="TextAppearance.Widget"/>
<style name="TextAppearance.Widget.Button" parent="TextAppearance.Small.Inverse">
<item name="textColor">@color/primary_text_light_nodisable</item>
@@ -946,22 +961,22 @@
</style>
<!-- @hide -->
- <style name="TextAppearance.SearchResult">
- <item name="textStyle">normal</item>
- <item name="textColor">?textColorPrimaryInverse</item>
- <item name="textColorHint">?textColorHintInverse</item>
- </style>
+ <style name="TextAppearance.SearchResult">
+ <item name="textStyle">normal</item>
+ <item name="textColor">?textColorPrimaryInverse</item>
+ <item name="textColorHint">?textColorHintInverse</item>
+ </style>
- <!-- @hide -->
- <style name="TextAppearance.SearchResult.Title">
- <item name="textSize">18sp</item>
- </style>
+ <!-- @hide -->
+ <style name="TextAppearance.SearchResult.Title">
+ <item name="textSize">18sp</item>
+ </style>
- <!-- @hide -->
- <style name="TextAppearance.SearchResult.Subtitle">
- <item name="textSize">14sp</item>
- <item name="textColor">?textColorSecondaryInverse</item>
- </style>
+ <!-- @hide -->
+ <style name="TextAppearance.SearchResult.Subtitle">
+ <item name="textSize">14sp</item>
+ <item name="textColor">?textColorSecondaryInverse</item>
+ </style>
<style name="TextAppearance.WindowTitle">
<item name="textColor">#fff</item>
@@ -1165,7 +1180,7 @@
</style>
<!-- Other Misc Styles -->
- <eat-comment />
+ <eat-comment/>
<style name="MediaButton">
<item name="background">@null</item>
@@ -1298,10 +1313,12 @@
<item name="textColor">?attr/textColorSecondary</item>
</style>
- <style name="TextAppearance.Widget.Toolbar.Title" parent="TextAppearance.Widget.ActionBar.Title">
+ <style name="TextAppearance.Widget.Toolbar.Title"
+ parent="TextAppearance.Widget.ActionBar.Title">
</style>
- <style name="TextAppearance.Widget.Toolbar.Subtitle" parent="TextAppearance.Widget.ActionBar.Subtitle">
+ <style name="TextAppearance.Widget.Toolbar.Subtitle"
+ parent="TextAppearance.Widget.ActionBar.Subtitle">
</style>
<style name="Widget.ActionButton">
@@ -1527,8 +1544,8 @@
<!-- The style for normal action button on notification -->
<style name="NotificationAction" parent="Widget.Material.Light.Button.Borderless.Small">
- <item name="textColor">@color/notification_action_button_text_color</item>
- <item name="background">@drawable/notification_material_action_background</item>
+ <item name="textColor">@color/notification_action_button_text_color</item>
+ <item name="background">@drawable/notification_material_action_background</item>
</style>
<!-- The style for emphasized action button on notification: Colored bordered ink button -->
@@ -1539,6 +1556,6 @@
<!-- The style for disabled action button on notification -->
<style name="NotificationTombstoneAction" parent="NotificationAction">
- <item name="textColor">#555555</item>
+ <item name="textColor">#555555</item>
</style>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 4131887..2abb0d8 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3100,6 +3100,10 @@
<java-symbol type="string" name="language_selection_title" />
<java-symbol type="string" name="search_language_hint" />
+ <!-- Work profile unlaunchable app alert dialog-->
+ <java-symbol type="style" name="AlertDialogWithEmergencyButton"/>
+ <java-symbol type="string" name="work_mode_dialer_off_message" />
+ <java-symbol type="string" name="work_mode_emergency_call_button" />
<java-symbol type="string" name="work_mode_off_title" />
<java-symbol type="string" name="work_mode_off_message" />
<java-symbol type="string" name="work_mode_turn_on" />
diff --git a/core/tests/BroadcastRadioTests/AndroidManifest.xml b/core/tests/BroadcastRadioTests/AndroidManifest.xml
index 869b484..8f655ef 100644
--- a/core/tests/BroadcastRadioTests/AndroidManifest.xml
+++ b/core/tests/BroadcastRadioTests/AndroidManifest.xml
@@ -15,7 +15,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.hardware.radio.tests">
+ package="com.android.frameworks.broadcastradiotests">
<uses-permission android:name="android.permission.ACCESS_BROADCAST_RADIO" />
@@ -25,7 +25,7 @@
<instrumentation
android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="android.hardware.radio.tests"
+ android:targetPackage="com.android.frameworks.broadcastradiotests"
android:label="Tests for Broadcast Radio APIs" >
</instrumentation>
</manifest>
diff --git a/core/tests/BroadcastRadioTests/AndroidTest.xml b/core/tests/BroadcastRadioTests/AndroidTest.xml
index ed88537..b7e93cd 100644
--- a/core/tests/BroadcastRadioTests/AndroidTest.xml
+++ b/core/tests/BroadcastRadioTests/AndroidTest.xml
@@ -25,7 +25,7 @@
<option name="test-tag" value="BroadcastRadioTests" />
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
- <option name="package" value="android.hardware.radio.tests" />
+ <option name="package" value="com.android.frameworks.broadcastradiotests" />
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
<option name="hidden-api-checks" value="false"/>
</test>
diff --git a/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/unittests/DefaultRadioTunerTest.java b/core/tests/BroadcastRadioTests/src/android/hardware/radio/DefaultRadioTunerTest.java
similarity index 90%
rename from core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/unittests/DefaultRadioTunerTest.java
rename to core/tests/BroadcastRadioTests/src/android/hardware/radio/DefaultRadioTunerTest.java
index 65e55a2..63de759 100644
--- a/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/unittests/DefaultRadioTunerTest.java
+++ b/core/tests/BroadcastRadioTests/src/android/hardware/radio/DefaultRadioTunerTest.java
@@ -14,17 +14,13 @@
* limitations under the License.
*/
-package android.hardware.radio.tests.unittests;
+package android.hardware.radio;
import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assert.assertThrows;
import android.graphics.Bitmap;
-import android.hardware.radio.ProgramList;
-import android.hardware.radio.ProgramSelector;
-import android.hardware.radio.RadioManager;
-import android.hardware.radio.RadioTuner;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -167,9 +163,7 @@
@Test
public void setConfigFlag_forRadioTuner_throwsException() {
UnsupportedOperationException thrown = assertThrows(UnsupportedOperationException.class,
- () -> {
- DEFAULT_RADIO_TUNER.setConfigFlag(/* flag= */ 1, /* value= */ false);
- });
+ () -> DEFAULT_RADIO_TUNER.setConfigFlag(/* flag= */ 1, /* value= */ false));
assertWithMessage("Exception for setting config flag on default radio tuner")
.that(thrown).hasMessageThat().contains("Setting config flag is not supported");
@@ -178,9 +172,7 @@
@Test
public void setParameters_forRadioTuner_throwsException() {
UnsupportedOperationException thrown = assertThrows(UnsupportedOperationException.class,
- () -> {
- DEFAULT_RADIO_TUNER.setParameters(Map.of("testKey", "testValue"));
- });
+ () -> DEFAULT_RADIO_TUNER.setParameters(Map.of("testKey", "testValue")));
assertWithMessage("Exception for setting parameters from default radio tuner")
.that(thrown).hasMessageThat().contains("Setting parameters is not supported");
@@ -189,9 +181,7 @@
@Test
public void getParameters_forRadioTuner_throwsException() {
UnsupportedOperationException thrown = assertThrows(UnsupportedOperationException.class,
- () -> {
- DEFAULT_RADIO_TUNER.getParameters(List.of("testKey"));
- });
+ () -> DEFAULT_RADIO_TUNER.getParameters(List.of("testKey")));
assertWithMessage("Exception for getting parameters from default radio tuner")
.that(thrown).hasMessageThat().contains("Getting parameters is not supported");
diff --git a/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/unittests/ProgramListTest.java b/core/tests/BroadcastRadioTests/src/android/hardware/radio/ProgramListTest.java
similarity index 97%
rename from core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/unittests/ProgramListTest.java
rename to core/tests/BroadcastRadioTests/src/android/hardware/radio/ProgramListTest.java
index 9a999e4..f807bad 100644
--- a/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/unittests/ProgramListTest.java
+++ b/core/tests/BroadcastRadioTests/src/android/hardware/radio/ProgramListTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.hardware.radio.tests.unittests;
+package android.hardware.radio;
import static com.google.common.truth.Truth.assertWithMessage;
@@ -29,14 +29,6 @@
import static org.mockito.Mockito.verify;
import android.content.Context;
-import android.hardware.radio.IRadioService;
-import android.hardware.radio.ITuner;
-import android.hardware.radio.ITunerCallback;
-import android.hardware.radio.ProgramList;
-import android.hardware.radio.ProgramSelector;
-import android.hardware.radio.RadioManager;
-import android.hardware.radio.RadioMetadata;
-import android.hardware.radio.RadioTuner;
import android.os.Parcel;
import android.os.RemoteException;
import android.util.ArraySet;
diff --git a/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/unittests/ProgramSelectorTest.java b/core/tests/BroadcastRadioTests/src/android/hardware/radio/ProgramSelectorTest.java
similarity index 99%
rename from core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/unittests/ProgramSelectorTest.java
rename to core/tests/BroadcastRadioTests/src/android/hardware/radio/ProgramSelectorTest.java
index 9399907..ae43a1c 100644
--- a/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/unittests/ProgramSelectorTest.java
+++ b/core/tests/BroadcastRadioTests/src/android/hardware/radio/ProgramSelectorTest.java
@@ -14,15 +14,13 @@
* limitations under the License.
*/
-package android.hardware.radio.tests.unittests;
+package android.hardware.radio;
import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assert.assertThrows;
import android.annotation.Nullable;
-import android.hardware.radio.ProgramSelector;
-import android.hardware.radio.RadioManager;
import android.os.Parcel;
import org.junit.Test;
diff --git a/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/unittests/RadioAnnouncementTest.java b/core/tests/BroadcastRadioTests/src/android/hardware/radio/RadioAnnouncementTest.java
similarity index 96%
rename from core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/unittests/RadioAnnouncementTest.java
rename to core/tests/BroadcastRadioTests/src/android/hardware/radio/RadioAnnouncementTest.java
index 6e1bb4b4..b0fb26a 100644
--- a/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/unittests/RadioAnnouncementTest.java
+++ b/core/tests/BroadcastRadioTests/src/android/hardware/radio/RadioAnnouncementTest.java
@@ -14,14 +14,12 @@
* limitations under the License.
*/
-package android.hardware.radio.tests.unittests;
+package android.hardware.radio;
import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assert.assertThrows;
-import android.hardware.radio.Announcement;
-import android.hardware.radio.ProgramSelector;
import android.os.Parcel;
import android.util.ArrayMap;
diff --git a/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/unittests/RadioManagerTest.java b/core/tests/BroadcastRadioTests/src/android/hardware/radio/RadioManagerTest.java
similarity index 98%
rename from core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/unittests/RadioManagerTest.java
rename to core/tests/BroadcastRadioTests/src/android/hardware/radio/RadioManagerTest.java
index afbf8c3..79a6b0d 100644
--- a/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/unittests/RadioManagerTest.java
+++ b/core/tests/BroadcastRadioTests/src/android/hardware/radio/RadioManagerTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.hardware.radio.tests.unittests;
+package android.hardware.radio;
import static com.google.common.truth.Truth.assertWithMessage;
@@ -30,14 +30,6 @@
import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.ApplicationInfo;
-import android.hardware.radio.Announcement;
-import android.hardware.radio.IAnnouncementListener;
-import android.hardware.radio.ICloseHandle;
-import android.hardware.radio.IRadioService;
-import android.hardware.radio.ProgramSelector;
-import android.hardware.radio.RadioManager;
-import android.hardware.radio.RadioMetadata;
-import android.hardware.radio.RadioTuner;
import android.os.Build;
import android.os.Parcel;
import android.os.RemoteException;
diff --git a/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/unittests/RadioMetadataTest.java b/core/tests/BroadcastRadioTests/src/android/hardware/radio/RadioMetadataTest.java
similarity index 98%
rename from core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/unittests/RadioMetadataTest.java
rename to core/tests/BroadcastRadioTests/src/android/hardware/radio/RadioMetadataTest.java
index 5771135..e348a51 100644
--- a/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/unittests/RadioMetadataTest.java
+++ b/core/tests/BroadcastRadioTests/src/android/hardware/radio/RadioMetadataTest.java
@@ -14,14 +14,13 @@
* limitations under the License.
*/
-package android.hardware.radio.tests.unittests;
+package android.hardware.radio;
import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assert.assertThrows;
import android.graphics.Bitmap;
-import android.hardware.radio.RadioMetadata;
import android.os.Parcel;
import org.junit.Test;
diff --git a/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/unittests/TunerAdapterTest.java b/core/tests/BroadcastRadioTests/src/android/hardware/radio/TunerAdapterTest.java
similarity index 98%
rename from core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/unittests/TunerAdapterTest.java
rename to core/tests/BroadcastRadioTests/src/android/hardware/radio/TunerAdapterTest.java
index c8b4493..487086c 100644
--- a/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/unittests/TunerAdapterTest.java
+++ b/core/tests/BroadcastRadioTests/src/android/hardware/radio/TunerAdapterTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.hardware.radio.tests.unittests;
+package android.hardware.radio;
import static com.google.common.truth.Truth.assertWithMessage;
@@ -32,13 +32,6 @@
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.graphics.Bitmap;
-import android.hardware.radio.IRadioService;
-import android.hardware.radio.ITuner;
-import android.hardware.radio.ITunerCallback;
-import android.hardware.radio.ProgramSelector;
-import android.hardware.radio.RadioManager;
-import android.hardware.radio.RadioMetadata;
-import android.hardware.radio.RadioTuner;
import android.os.Build;
import android.os.RemoteException;
diff --git a/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/functional/RadioTunerTest.java b/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/functional/RadioTunerTest.java
deleted file mode 100644
index cabeb13..0000000
--- a/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/functional/RadioTunerTest.java
+++ /dev/null
@@ -1,428 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.hardware.radio.tests.functional;
-
-import static org.junit.Assert.*;
-import static org.junit.Assume.*;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Mockito.after;
-import static org.mockito.Mockito.atMost;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.timeout;
-import static org.mockito.Mockito.verify;
-import static org.testng.Assert.assertThrows;
-
-import android.Manifest;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.hardware.radio.ProgramSelector;
-import android.hardware.radio.RadioManager;
-import android.hardware.radio.RadioTuner;
-import android.util.Log;
-
-import androidx.test.InstrumentationRegistry;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-import org.mockito.junit.MockitoJUnitRunner;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * A test for broadcast radio API.
- */
-@RunWith(MockitoJUnitRunner.class)
-public class RadioTunerTest {
- private static final String TAG = "BroadcastRadioTests.RadioTuner";
-
- public final Context mContext = InstrumentationRegistry.getContext();
-
- private final int kConfigCallbackTimeoutMs = 10000;
- private final int kCancelTimeoutMs = 1000;
- private final int kTuneCallbackTimeoutMs = 30000;
- private final int kFullScanTimeoutMs = 60000;
-
- private RadioManager mRadioManager;
- private RadioTuner mRadioTuner;
- private RadioManager.ModuleProperties mModule;
- private final List<RadioManager.ModuleProperties> mModules = new ArrayList<>();
- @Mock private RadioTuner.Callback mCallback;
-
- RadioManager.AmBandDescriptor mAmBandDescriptor;
- RadioManager.FmBandDescriptor mFmBandDescriptor;
-
- RadioManager.BandConfig mAmBandConfig;
- RadioManager.BandConfig mFmBandConfig;
-
- @Before
- public void setup() {
- MockitoAnnotations.initMocks(this);
-
- // check if radio is supported and skip the test if it's not
- PackageManager packageManager = mContext.getPackageManager();
- boolean isRadioSupported = packageManager.hasSystemFeature(
- PackageManager.FEATURE_BROADCAST_RADIO);
- assumeTrue(isRadioSupported);
-
- // Check radio access permission
- int res = mContext.checkCallingOrSelfPermission(Manifest.permission.ACCESS_BROADCAST_RADIO);
- assertEquals("ACCESS_BROADCAST_RADIO permission not granted",
- PackageManager.PERMISSION_GRANTED, res);
-
- mRadioManager = (RadioManager)mContext.getSystemService(Context.RADIO_SERVICE);
- assertNotNull(mRadioManager);
-
- int status = mRadioManager.listModules(mModules);
- assertEquals(RadioManager.STATUS_OK, status);
- assertFalse(mModules.isEmpty());
- }
-
- @After
- public void tearDown() {
- mRadioManager = null;
- mModules.clear();
- if (mRadioTuner != null) {
- mRadioTuner.close();
- mRadioTuner = null;
- }
- resetCallback();
- }
-
- private void openTuner() {
- openTuner(true);
- }
-
- private void resetCallback() {
- verify(mCallback, never()).onError(anyInt());
- verify(mCallback, never()).onTuneFailed(anyInt(), any());
- verify(mCallback, never()).onControlChanged(anyBoolean());
- Mockito.reset(mCallback);
- }
-
- private void openTuner(boolean withAudio) {
- assertNull(mRadioTuner);
-
- // find FM band and build its config
- mModule = mModules.get(0);
-
- for (RadioManager.BandDescriptor band : mModule.getBands()) {
- Log.d(TAG, "Band: " + band);
- int bandType = band.getType();
- if (bandType == RadioManager.BAND_AM || bandType == RadioManager.BAND_AM_HD) {
- mAmBandDescriptor = (RadioManager.AmBandDescriptor)band;
- }
- if (bandType == RadioManager.BAND_FM || bandType == RadioManager.BAND_FM_HD) {
- mFmBandDescriptor = (RadioManager.FmBandDescriptor)band;
- }
- }
- assertNotNull(mAmBandDescriptor);
- assertNotNull(mFmBandDescriptor);
- mAmBandConfig = new RadioManager.AmBandConfig.Builder(mAmBandDescriptor).build();
- mFmBandConfig = new RadioManager.FmBandConfig.Builder(mFmBandDescriptor).build();
-
- mRadioTuner = mRadioManager.openTuner(mModule.getId(),
- mFmBandConfig, withAudio, mCallback, null);
- if (!withAudio) {
- // non-audio sessions might not be supported - if so, then skip the test
- assumeNotNull(mRadioTuner);
- }
- assertNotNull(mRadioTuner);
- verify(mCallback, timeout(kConfigCallbackTimeoutMs)).onConfigurationChanged(any());
- resetCallback();
-
- boolean isAntennaConnected = mRadioTuner.isAntennaConnected();
- assertTrue(isAntennaConnected);
- }
-
- @Test
- public void testOpenTuner() {
- openTuner();
- }
-
- @Test
- public void testReopenTuner() throws Throwable {
- openTuner();
- mRadioTuner.close();
- mRadioTuner = null;
- Thread.sleep(100); // TODO(b/36122635): force reopen
- openTuner();
- }
-
- @Test
- public void testDoubleClose() {
- openTuner();
- mRadioTuner.close();
- mRadioTuner.close();
- }
-
- @Test
- public void testUseAfterClose() {
- openTuner();
- mRadioTuner.close();
- int ret = mRadioTuner.cancel();
- assertEquals(RadioManager.STATUS_INVALID_OPERATION, ret);
- }
-
- @Test
- public void testSetAndGetConfiguration() {
- openTuner();
-
- // set
- int ret = mRadioTuner.setConfiguration(mAmBandConfig);
- assertEquals(RadioManager.STATUS_OK, ret);
- verify(mCallback, timeout(kConfigCallbackTimeoutMs)).onConfigurationChanged(any());
-
- // get
- RadioManager.BandConfig[] config = new RadioManager.BandConfig[1];
- ret = mRadioTuner.getConfiguration(config);
- assertEquals(RadioManager.STATUS_OK, ret);
-
- assertEquals(mAmBandConfig, config[0]);
- }
-
- @Test
- public void testSetBadConfiguration() throws Throwable {
- openTuner();
-
- // set null config
- int ret = mRadioTuner.setConfiguration(null);
- assertEquals(RadioManager.STATUS_BAD_VALUE, ret);
- verify(mCallback, never()).onConfigurationChanged(any());
-
- // setting good config should recover
- ret = mRadioTuner.setConfiguration(mAmBandConfig);
- assertEquals(RadioManager.STATUS_OK, ret);
- verify(mCallback, timeout(kConfigCallbackTimeoutMs)).onConfigurationChanged(any());
- }
-
- @Test
- public void testMute() {
- openTuner();
-
- boolean isMuted = mRadioTuner.getMute();
- assertFalse(isMuted);
-
- int ret = mRadioTuner.setMute(true);
- assertEquals(RadioManager.STATUS_OK, ret);
- isMuted = mRadioTuner.getMute();
- assertTrue(isMuted);
-
- ret = mRadioTuner.setMute(false);
- assertEquals(RadioManager.STATUS_OK, ret);
- isMuted = mRadioTuner.getMute();
- assertFalse(isMuted);
- }
-
- @Test
- public void testMuteNoAudio() {
- openTuner(false);
-
- int ret = mRadioTuner.setMute(false);
- assertEquals(RadioManager.STATUS_ERROR, ret);
-
- boolean isMuted = mRadioTuner.getMute();
- assertTrue(isMuted);
- }
-
- @Test
- public void testStep() {
- openTuner();
-
- int ret = mRadioTuner.step(RadioTuner.DIRECTION_DOWN, true);
- assertEquals(RadioManager.STATUS_OK, ret);
- verify(mCallback, timeout(kTuneCallbackTimeoutMs)).onProgramInfoChanged(any());
-
- resetCallback();
-
- ret = mRadioTuner.step(RadioTuner.DIRECTION_UP, false);
- assertEquals(RadioManager.STATUS_OK, ret);
- verify(mCallback, timeout(kTuneCallbackTimeoutMs)).onProgramInfoChanged(any());
- }
-
- @Test
- public void testStepLoop() {
- openTuner();
-
- for (int i = 0; i < 10; i++) {
- Log.d(TAG, "step loop iteration " + (i + 1));
-
- int ret = mRadioTuner.step(RadioTuner.DIRECTION_DOWN, true);
- assertEquals(RadioManager.STATUS_OK, ret);
- verify(mCallback, timeout(kTuneCallbackTimeoutMs)).onProgramInfoChanged(any());
-
- resetCallback();
- }
- }
-
- @Test
- public void testTuneAndGetPI() {
- openTuner();
-
- int channel = mFmBandConfig.getLowerLimit() + mFmBandConfig.getSpacing();
-
- // test tune
- int ret = mRadioTuner.tune(channel, 0);
- assertEquals(RadioManager.STATUS_OK, ret);
- ArgumentCaptor<RadioManager.ProgramInfo> infoc =
- ArgumentCaptor.forClass(RadioManager.ProgramInfo.class);
- verify(mCallback, timeout(kTuneCallbackTimeoutMs))
- .onProgramInfoChanged(infoc.capture());
- assertEquals(channel, infoc.getValue().getChannel());
-
- // test getProgramInformation
- RadioManager.ProgramInfo[] info = new RadioManager.ProgramInfo[1];
- ret = mRadioTuner.getProgramInformation(info);
- assertEquals(RadioManager.STATUS_OK, ret);
- assertNotNull(info[0]);
- assertEquals(channel, info[0].getChannel());
- Log.d(TAG, "PI: " + info[0].toString());
- }
-
- @Test
- public void testDummyCancel() {
- openTuner();
-
- int ret = mRadioTuner.cancel();
- assertEquals(RadioManager.STATUS_OK, ret);
- }
-
- @Test
- public void testLateCancel() {
- openTuner();
-
- int ret = mRadioTuner.step(RadioTuner.DIRECTION_DOWN, false);
- assertEquals(RadioManager.STATUS_OK, ret);
- verify(mCallback, timeout(kTuneCallbackTimeoutMs)).onProgramInfoChanged(any());
-
- int cancelRet = mRadioTuner.cancel();
- assertEquals(RadioManager.STATUS_OK, cancelRet);
- }
-
- @Test
- public void testScanAndCancel() {
- openTuner();
-
- /* There is a possible race condition between scan and cancel commands - the scan may finish
- * before cancel command is issued. Thus we accept both outcomes in this test.
- */
- int scanRet = mRadioTuner.scan(RadioTuner.DIRECTION_DOWN, true);
- int cancelRet = mRadioTuner.cancel();
-
- assertEquals(RadioManager.STATUS_OK, scanRet);
- assertEquals(RadioManager.STATUS_OK, cancelRet);
-
- verify(mCallback, after(kCancelTimeoutMs).atMost(1))
- .onTuneFailed(eq(RadioTuner.TUNER_RESULT_CANCELED), any());
- verify(mCallback, atMost(1)).onProgramInfoChanged(any());
- Mockito.reset(mCallback);
- }
-
- @Test
- public void testStartBackgroundScan() {
- openTuner();
-
- boolean ret = mRadioTuner.startBackgroundScan();
- boolean isSupported = mModule.isBackgroundScanningSupported();
- assertEquals(isSupported, ret);
- }
-
- @Test
- public void testGetProgramList() {
- openTuner();
-
- try {
- Map<String, String> filter = new HashMap<>();
- filter.put("com.google.dummy", "dummy");
- List<RadioManager.ProgramInfo> list = mRadioTuner.getProgramList(filter);
- assertNotNull(list);
- } catch (IllegalStateException e) {
- // the list may or may not be ready at this point
- Log.i(TAG, "Background list is not ready");
- }
- }
-
- @Test
- public void testTuneFromProgramList() {
- openTuner();
-
- List<RadioManager.ProgramInfo> list;
-
- try {
- list = mRadioTuner.getProgramList(null);
- assertNotNull(list);
- } catch (IllegalStateException e) {
- Log.i(TAG, "Background list is not ready, trying to fix it");
-
- boolean success = mRadioTuner.startBackgroundScan();
- assertTrue(success);
- verify(mCallback, timeout(kFullScanTimeoutMs)).onBackgroundScanComplete();
-
- list = mRadioTuner.getProgramList(null);
- assertNotNull(list);
- }
-
- if (list.isEmpty()) {
- Log.i(TAG, "Program list is empty, can't test tune");
- return;
- }
-
- ProgramSelector sel = list.get(0).getSelector();
- mRadioTuner.tune(sel);
- ArgumentCaptor<RadioManager.ProgramInfo> infoc =
- ArgumentCaptor.forClass(RadioManager.ProgramInfo.class);
- verify(mCallback, timeout(kTuneCallbackTimeoutMs)).onProgramInfoChanged(infoc.capture());
- assertEquals(sel, infoc.getValue().getSelector());
- }
-
- @Test
- public void testForcedAnalog() {
- openTuner();
-
- boolean isSupported = true;
- boolean isForced;
- try {
- isForced = mRadioTuner.isAnalogForced();
- assertFalse(isForced);
- } catch (IllegalStateException ex) {
- Log.i(TAG, "Forced analog switch is not supported by this tuner");
- isSupported = false;
- }
-
- if (isSupported) {
- mRadioTuner.setAnalogForced(true);
- isForced = mRadioTuner.isAnalogForced();
- assertTrue(isForced);
-
- mRadioTuner.setAnalogForced(false);
- isForced = mRadioTuner.isAnalogForced();
- assertFalse(isForced);
- } else {
- assertThrows(IllegalStateException.class, () -> mRadioTuner.setAnalogForced(true));
- }
- }
-}
diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/AidlTestUtils.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/AidlTestUtils.java
index 82db716..cce1b2b 100644
--- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/AidlTestUtils.java
+++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/AidlTestUtils.java
@@ -21,10 +21,15 @@
import android.hardware.broadcastradio.ProgramInfo;
import android.hardware.broadcastradio.ProgramListChunk;
import android.hardware.broadcastradio.VendorKeyValue;
+import android.hardware.radio.ProgramList;
import android.hardware.radio.ProgramSelector;
import android.hardware.radio.RadioManager;
import android.hardware.radio.RadioMetadata;
+import android.os.RemoteException;
import android.util.ArrayMap;
+import android.util.ArraySet;
+
+import java.util.List;
final class AidlTestUtils {
@@ -94,6 +99,14 @@
return makeHalProgramInfo(hwSel, hwSel.primaryId, hwSel.primaryId, hwSignalQuality);
}
+ static ProgramInfo programInfoToHalProgramInfo(RadioManager.ProgramInfo info) {
+ return makeHalProgramInfo(
+ ConversionUtils.programSelectorToHalProgramSelector(info.getSelector()),
+ ConversionUtils.identifierToHalProgramIdentifier(info.getLogicallyTunedTo()),
+ ConversionUtils.identifierToHalProgramIdentifier(info.getPhysicallyTunedTo()),
+ info.getSignalStrength());
+ }
+
static ProgramInfo makeHalProgramInfo(
android.hardware.broadcastradio.ProgramSelector hwSel,
ProgramIdentifier logicallyTunedTo, ProgramIdentifier physicallyTunedTo,
@@ -108,7 +121,23 @@
return hwInfo;
}
- static ProgramListChunk makeProgramListChunk(boolean purge, boolean complete,
+ static ProgramListChunk makeHalChunk(boolean purge, boolean complete,
+ List<RadioManager.ProgramInfo> modified, List<ProgramSelector.Identifier> removed) {
+ ProgramInfo[] halModified =
+ new android.hardware.broadcastradio.ProgramInfo[modified.size()];
+ for (int i = 0; i < modified.size(); i++) {
+ halModified[i] = programInfoToHalProgramInfo(modified.get(i));
+ }
+
+ ProgramIdentifier[] halRemoved =
+ new android.hardware.broadcastradio.ProgramIdentifier[removed.size()];
+ for (int i = 0; i < removed.size(); i++) {
+ halRemoved[i] = ConversionUtils.identifierToHalProgramIdentifier(removed.get(i));
+ }
+ return makeHalChunk(purge, complete, halModified, halRemoved);
+ }
+
+ static ProgramListChunk makeHalChunk(boolean purge, boolean complete,
ProgramInfo[] modified, ProgramIdentifier[] removed) {
ProgramListChunk halChunk = new ProgramListChunk();
halChunk.purge = purge;
@@ -118,6 +147,21 @@
return halChunk;
}
+ static ProgramList.Chunk makeChunk(boolean purge, boolean complete,
+ List<RadioManager.ProgramInfo> modified,
+ List<ProgramSelector.Identifier> removed) throws RemoteException {
+ ArraySet<RadioManager.ProgramInfo> modifiedSet = new ArraySet<>();
+ if (modified != null) {
+ modifiedSet.addAll(modified);
+ }
+ ArraySet<ProgramSelector.Identifier> removedSet = new ArraySet<>();
+ if (removed != null) {
+ removedSet.addAll(removed);
+ }
+ ProgramList.Chunk chunk = new ProgramList.Chunk(purge, complete, modifiedSet, removedSet);
+ return chunk;
+ }
+
static VendorKeyValue makeVendorKeyValue(String vendorKey, String vendorValue) {
VendorKeyValue vendorKeyValue = new VendorKeyValue();
vendorKeyValue.key = vendorKey;
diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsTest.java
index 710c150..5d0e076 100644
--- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsTest.java
+++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsTest.java
@@ -328,7 +328,7 @@
TEST_HAL_DAB_SID_EXT_ID, TEST_HAL_DAB_FREQUENCY_ID, TEST_SIGNAL_QUALITY);
RadioManager.ProgramInfo dabInfo =
ConversionUtils.programInfoFromHalProgramInfo(halDabInfo);
- ProgramListChunk halChunk = AidlTestUtils.makeProgramListChunk(purge, complete,
+ ProgramListChunk halChunk = AidlTestUtils.makeHalChunk(purge, complete,
new ProgramInfo[]{halDabInfo},
new ProgramIdentifier[]{TEST_HAL_VENDOR_ID, TEST_HAL_FM_FREQUENCY_ID});
@@ -353,7 +353,7 @@
TEST_HAL_DAB_ENSEMBLE_ID, TEST_HAL_DAB_FREQUENCY_ID});
ProgramInfo halDabInfo = AidlTestUtils.makeHalProgramInfo(halDabSelector,
TEST_HAL_DAB_SID_EXT_ID, TEST_HAL_DAB_ENSEMBLE_ID, TEST_SIGNAL_QUALITY);
- ProgramListChunk halChunk = AidlTestUtils.makeProgramListChunk(purge, complete,
+ ProgramListChunk halChunk = AidlTestUtils.makeHalChunk(purge, complete,
new ProgramInfo[]{halDabInfo}, new ProgramIdentifier[]{TEST_HAL_FM_FREQUENCY_ID});
ProgramList.Chunk chunk = ConversionUtils.chunkFromHalProgramListChunk(halChunk);
diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ProgramInfoCacheTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ProgramInfoCacheTest.java
new file mode 100644
index 0000000..d54397e
--- /dev/null
+++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ProgramInfoCacheTest.java
@@ -0,0 +1,409 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.broadcastradio.aidl;
+
+import android.hardware.broadcastradio.ProgramIdentifier;
+import android.hardware.broadcastradio.ProgramInfo;
+import android.hardware.broadcastradio.ProgramListChunk;
+import android.hardware.radio.ProgramList;
+import android.hardware.radio.ProgramSelector;
+import android.hardware.radio.RadioManager;
+import android.os.RemoteException;
+import android.util.ArraySet;
+
+import com.google.common.truth.Expect;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Unit tests for AIDL ProgramInfoCache
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class ProgramInfoCacheTest {
+
+ private static final int TEST_SIGNAL_QUALITY = 90;
+
+ private static final ProgramSelector.Identifier TEST_FM_FREQUENCY_ID =
+ new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY,
+ /* value= */ 88_500);
+ private static final RadioManager.ProgramInfo TEST_FM_INFO = AidlTestUtils.makeProgramInfo(
+ AidlTestUtils.makeProgramSelector(ProgramSelector.PROGRAM_TYPE_FM,
+ TEST_FM_FREQUENCY_ID), TEST_FM_FREQUENCY_ID, TEST_FM_FREQUENCY_ID,
+ TEST_SIGNAL_QUALITY);
+ private static final RadioManager.ProgramInfo TEST_FM_INFO_MODIFIED =
+ AidlTestUtils.makeProgramInfo(AidlTestUtils.makeProgramSelector(
+ ProgramSelector.PROGRAM_TYPE_FM, TEST_FM_FREQUENCY_ID), TEST_FM_FREQUENCY_ID,
+ TEST_FM_FREQUENCY_ID, /* signalQuality= */ 99);
+
+ private static final ProgramSelector.Identifier TEST_AM_FREQUENCY_ID =
+ new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY,
+ /* value= */ 1_700);
+ private static final RadioManager.ProgramInfo TEST_AM_INFO = AidlTestUtils.makeProgramInfo(
+ AidlTestUtils.makeProgramSelector(ProgramSelector.PROGRAM_TYPE_FM,
+ TEST_AM_FREQUENCY_ID), TEST_AM_FREQUENCY_ID, TEST_AM_FREQUENCY_ID,
+ TEST_SIGNAL_QUALITY);
+
+ private static final ProgramSelector.Identifier TEST_RDS_PI_ID =
+ new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_RDS_PI,
+ /* value= */ 15_019);
+ private static final RadioManager.ProgramInfo TEST_RDS_INFO = AidlTestUtils.makeProgramInfo(
+ AidlTestUtils.makeProgramSelector(ProgramSelector.PROGRAM_TYPE_FM, TEST_RDS_PI_ID),
+ TEST_RDS_PI_ID, new ProgramSelector.Identifier(
+ ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY, /* value= */ 89_500),
+ TEST_SIGNAL_QUALITY);
+
+ private static final ProgramSelector.Identifier TEST_DAB_DMB_SID_EXT_ID =
+ new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_DMB_SID_EXT,
+ /* value= */ 0xA000000111L);
+ private static final ProgramSelector.Identifier TEST_DAB_ENSEMBLE_ID =
+ new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_ENSEMBLE,
+ /* value= */ 0x1001);
+ private static final ProgramSelector.Identifier TEST_DAB_FREQUENCY_ID =
+ new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_FREQUENCY,
+ /* value= */ 220_352);
+ private static final RadioManager.ProgramInfo TEST_DAB_INFO = AidlTestUtils.makeProgramInfo(
+ new ProgramSelector(ProgramSelector.PROGRAM_TYPE_DAB, TEST_DAB_DMB_SID_EXT_ID,
+ new ProgramSelector.Identifier[]{TEST_DAB_FREQUENCY_ID, TEST_DAB_ENSEMBLE_ID},
+ /* vendorIds= */ null), TEST_DAB_DMB_SID_EXT_ID, TEST_DAB_FREQUENCY_ID,
+ TEST_SIGNAL_QUALITY);
+
+ private static final ProgramSelector.Identifier TEST_VENDOR_ID =
+ new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_VENDOR_START,
+ /* value= */ 9_001);
+ private static final RadioManager.ProgramInfo TEST_VENDOR_INFO = AidlTestUtils.makeProgramInfo(
+ AidlTestUtils.makeProgramSelector(ProgramSelector.PROGRAM_TYPE_VENDOR_START,
+ TEST_VENDOR_ID), TEST_VENDOR_ID, TEST_VENDOR_ID, TEST_SIGNAL_QUALITY);
+
+ private static final ProgramInfoCache FULL_PROGRAM_INFO_CACHE = new ProgramInfoCache(
+ /* filter= */ null, /* complete= */ true,
+ TEST_FM_INFO, TEST_AM_INFO, TEST_RDS_INFO, TEST_DAB_INFO, TEST_VENDOR_INFO);
+
+ @Rule
+ public final Expect expect = Expect.create();
+
+ @Test
+ public void isComplete_forCompleteProgramInfoCache_returnsTrue() {
+ expect.withMessage("Complete program info cache")
+ .that(FULL_PROGRAM_INFO_CACHE.isComplete()).isTrue();
+ }
+
+ @Test
+ public void isComplete_forIncompleteProgramInfoCache_returnsFalse() {
+ ProgramInfoCache programInfoCache = new ProgramInfoCache(/* filter= */ null,
+ /* complete= */ false);
+ expect.withMessage("Incomplete program info cache")
+ .that(programInfoCache.isComplete()).isFalse();
+ }
+
+ @Test
+ public void getFilter_forProgramInfoCache() {
+ ProgramList.Filter fmFilter = new ProgramList.Filter(
+ Set.of(ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY), new ArraySet<>(),
+ /* includeCategories= */ true, /* excludeModifications= */ false);
+ ProgramInfoCache fmProgramInfoCache = new ProgramInfoCache(fmFilter);
+
+ expect.withMessage("Program info cache filter")
+ .that(fmProgramInfoCache.getFilter()).isEqualTo(fmFilter);
+ }
+
+ @Test
+ public void updateFromHalProgramListChunk_withPurgingCompleteChunk() {
+ ProgramInfoCache cache = new ProgramInfoCache(/* filter= */ null,
+ /* complete= */ false, TEST_FM_INFO);
+ ProgramListChunk chunk = AidlTestUtils.makeHalChunk(/* purge= */ true, /* complete= */ true,
+ new ProgramInfo[]{AidlTestUtils.programInfoToHalProgramInfo(TEST_RDS_INFO),
+ AidlTestUtils.programInfoToHalProgramInfo(TEST_VENDOR_INFO)},
+ new ProgramIdentifier[]{});
+
+ cache.updateFromHalProgramListChunk(chunk);
+
+ expect.withMessage("Program cache updated with purge-enabled and complete chunk")
+ .that(cache.toProgramInfoList())
+ .containsExactly(TEST_RDS_INFO, TEST_VENDOR_INFO);
+ expect.withMessage("Complete program cache").that(cache.isComplete()).isTrue();
+ }
+
+ @Test
+ public void updateFromHalProgramListChunk_withNonPurgingIncompleteChunk() {
+ ProgramInfoCache cache = new ProgramInfoCache(/* filter= */ null,
+ /* complete= */ false, TEST_FM_INFO, TEST_RDS_INFO, TEST_AM_INFO);
+ ProgramListChunk chunk = AidlTestUtils.makeHalChunk(/* purge= */ false,
+ /* complete= */ false,
+ new ProgramInfo[]{AidlTestUtils.programInfoToHalProgramInfo(TEST_FM_INFO_MODIFIED),
+ AidlTestUtils.programInfoToHalProgramInfo(TEST_VENDOR_INFO)},
+ new ProgramIdentifier[]{ConversionUtils.identifierToHalProgramIdentifier(
+ TEST_RDS_PI_ID)});
+
+ cache.updateFromHalProgramListChunk(chunk);
+
+ expect.withMessage("Program cache updated with non-purging and incomplete chunk")
+ .that(cache.toProgramInfoList())
+ .containsExactly(TEST_FM_INFO_MODIFIED, TEST_VENDOR_INFO, TEST_AM_INFO);
+ expect.withMessage("Incomplete program cache").that(cache.isComplete()).isFalse();
+ }
+
+ @Test
+ public void filterAndUpdateFromInternal_withNullFilter() {
+ ProgramInfoCache cache = new ProgramInfoCache(/* filter= */ null,
+ /* complete= */ true);
+
+ cache.filterAndUpdateFromInternal(FULL_PROGRAM_INFO_CACHE, /* purge= */ false);
+
+ expect.withMessage("Program cache filtered by null filter")
+ .that(cache.toProgramInfoList())
+ .containsExactly(TEST_FM_INFO, TEST_AM_INFO, TEST_RDS_INFO, TEST_DAB_INFO,
+ TEST_VENDOR_INFO);
+ }
+
+ @Test
+ public void filterAndUpdateFromInternal_withEmptyFilter() {
+ ProgramInfoCache cache = new ProgramInfoCache(new ProgramList.Filter(new ArraySet<>(),
+ new ArraySet<>(),
+ /* includeCategories= */ true, /* excludeModifications= */ false));
+
+ cache.filterAndUpdateFromInternal(FULL_PROGRAM_INFO_CACHE, /* purge= */ false);
+
+ expect.withMessage("Program cache filtered by empty filter")
+ .that(cache.toProgramInfoList())
+ .containsExactly(TEST_FM_INFO, TEST_AM_INFO, TEST_RDS_INFO, TEST_DAB_INFO,
+ TEST_VENDOR_INFO);
+ }
+
+ @Test
+ public void filterAndUpdateFromInternal_withFilterByIdentifierType() {
+ ProgramInfoCache cache = new ProgramInfoCache(
+ new ProgramList.Filter(Set.of(ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY,
+ ProgramSelector.IDENTIFIER_TYPE_RDS_PI), new ArraySet<>(),
+ /* includeCategories= */ true, /* excludeModifications= */ false));
+
+ cache.filterAndUpdateFromInternal(FULL_PROGRAM_INFO_CACHE, /* purge= */ false);
+
+ expect.withMessage("Program cache filtered by identifier type")
+ .that(cache.toProgramInfoList())
+ .containsExactly(TEST_FM_INFO, TEST_AM_INFO, TEST_RDS_INFO);
+ }
+
+ @Test
+ public void filterAndUpdateFromInternal_withFilterByIdentifier() {
+ ProgramInfoCache cache = new ProgramInfoCache(new ProgramList.Filter(
+ new ArraySet<>(), Set.of(TEST_FM_FREQUENCY_ID, TEST_DAB_DMB_SID_EXT_ID),
+ /* includeCategories= */ true, /* excludeModifications= */ false));
+ int maxNumModifiedPerChunk = 2;
+ int maxNumRemovedPerChunk = 2;
+
+ List<ProgramList.Chunk> programListChunks = cache.filterAndUpdateFromInternal(
+ FULL_PROGRAM_INFO_CACHE, /* purge= */ true, maxNumModifiedPerChunk,
+ maxNumRemovedPerChunk);
+
+ expect.withMessage("Program cache filtered by identifier")
+ .that(cache.toProgramInfoList()).containsExactly(TEST_FM_INFO, TEST_DAB_INFO);
+ verifyChunkListPurge(programListChunks, /* purge= */ true);
+ verifyChunkListComplete(programListChunks, FULL_PROGRAM_INFO_CACHE.isComplete());
+ verifyChunkListModified(programListChunks, maxNumModifiedPerChunk, TEST_FM_INFO,
+ TEST_DAB_INFO);
+ verifyChunkListRemoved(programListChunks, maxNumRemovedPerChunk);
+ }
+
+ @Test
+ public void filterAndUpdateFromInternal_withFilterExcludingCategories() {
+ ProgramInfoCache cache = new ProgramInfoCache(new ProgramList.Filter(new ArraySet<>(),
+ new ArraySet<>(), /* includeCategories= */ false,
+ /* excludeModifications= */ false));
+ int maxNumModifiedPerChunk = 3;
+ int maxNumRemovedPerChunk = 2;
+
+ List<ProgramList.Chunk> programListChunks = cache.filterAndUpdateFromInternal(
+ FULL_PROGRAM_INFO_CACHE, /* purge= */ false, maxNumModifiedPerChunk,
+ maxNumRemovedPerChunk);
+
+ expect.withMessage("Program cache filtered by excluding categories")
+ .that(cache.toProgramInfoList())
+ .containsExactly(TEST_FM_INFO, TEST_AM_INFO, TEST_RDS_INFO, TEST_DAB_INFO);
+ verifyChunkListPurge(programListChunks, /* purge= */ true);
+ verifyChunkListComplete(programListChunks, FULL_PROGRAM_INFO_CACHE.isComplete());
+ verifyChunkListModified(programListChunks, maxNumModifiedPerChunk, TEST_FM_INFO,
+ TEST_AM_INFO, TEST_RDS_INFO, TEST_DAB_INFO);
+ verifyChunkListRemoved(programListChunks, maxNumRemovedPerChunk);
+ }
+
+ @Test
+ public void filterAndUpdateFromInternal_withFilterExcludingModifications() {
+ ProgramList.Filter filterExcludingModifications = new ProgramList.Filter(new ArraySet<>(),
+ new ArraySet<>(), /* includeCategories= */ true,
+ /* excludeModifications= */ true);
+ ProgramInfoCache cache = new ProgramInfoCache(filterExcludingModifications,
+ /* complete= */ true, TEST_FM_INFO, TEST_RDS_INFO, TEST_AM_INFO, TEST_DAB_INFO);
+ ProgramInfoCache halCache = new ProgramInfoCache(/* filter= */ null, /* complete= */ false,
+ TEST_FM_INFO_MODIFIED, TEST_VENDOR_INFO);
+ int maxNumModifiedPerChunk = 2;
+ int maxNumRemovedPerChunk = 2;
+
+ List<ProgramList.Chunk> programListChunks = cache.filterAndUpdateFromInternal(halCache,
+ /* purge= */ false, maxNumModifiedPerChunk, maxNumRemovedPerChunk);
+
+ expect.withMessage("Program cache filtered by excluding modifications")
+ .that(cache.toProgramInfoList())
+ .containsExactly(TEST_FM_INFO, TEST_VENDOR_INFO);
+ verifyChunkListPurge(programListChunks, /* purge= */ false);
+ verifyChunkListComplete(programListChunks, halCache.isComplete());
+ verifyChunkListModified(programListChunks, maxNumModifiedPerChunk, TEST_VENDOR_INFO);
+ verifyChunkListRemoved(programListChunks, maxNumRemovedPerChunk, TEST_RDS_PI_ID,
+ TEST_AM_FREQUENCY_ID, TEST_DAB_DMB_SID_EXT_ID);
+ }
+
+ @Test
+ public void filterAndUpdateFromInternal_withPurge() {
+ ProgramInfoCache cache = new ProgramInfoCache(new ProgramList.Filter(new ArraySet<>(),
+ new ArraySet<>(), /* includeCategories= */ true,
+ /* excludeModifications= */ false),
+ /* complete= */ true, TEST_FM_INFO, TEST_RDS_INFO);
+ ProgramInfoCache halCache = new ProgramInfoCache(/* filter= */ null, /* complete= */ false,
+ TEST_FM_INFO_MODIFIED, TEST_DAB_INFO, TEST_VENDOR_INFO);
+ int maxNumModifiedPerChunk = 2;
+ int maxNumRemovedPerChunk = 2;
+
+ List<ProgramList.Chunk> programListChunks = cache.filterAndUpdateFromInternal(halCache,
+ /* purge= */ true, maxNumModifiedPerChunk, maxNumRemovedPerChunk);
+
+ expect.withMessage("Purged program cache").that(cache.toProgramInfoList())
+ .containsExactly(TEST_FM_INFO_MODIFIED, TEST_DAB_INFO, TEST_VENDOR_INFO);
+ verifyChunkListPurge(programListChunks, /* purge= */ true);
+ verifyChunkListComplete(programListChunks, halCache.isComplete());
+ verifyChunkListModified(programListChunks, maxNumModifiedPerChunk, TEST_FM_INFO_MODIFIED,
+ TEST_DAB_INFO, TEST_VENDOR_INFO);
+ verifyChunkListRemoved(programListChunks, maxNumRemovedPerChunk);
+ }
+
+ @Test
+ public void filterAndApplyChunkInternal_withPurgingIncompleteChunk() throws RemoteException {
+ ProgramInfoCache cache = new ProgramInfoCache(/* filter= */ null,
+ /* complete= */ false, TEST_FM_INFO, TEST_DAB_INFO);
+ ProgramList.Chunk chunk = AidlTestUtils.makeChunk(/* purge= */ true, /* complete= */ false,
+ List.of(TEST_FM_INFO_MODIFIED, TEST_RDS_INFO, TEST_VENDOR_INFO),
+ List.of(TEST_DAB_DMB_SID_EXT_ID));
+ int maxNumModifiedPerChunk = 2;
+ int maxNumRemovedPerChunk = 2;
+
+ List<ProgramList.Chunk> programListChunks = cache.filterAndApplyChunkInternal(chunk,
+ maxNumModifiedPerChunk, maxNumRemovedPerChunk);
+
+ expect.withMessage("Program cache applied with non-purging and complete chunk")
+ .that(cache.toProgramInfoList())
+ .containsExactly(TEST_FM_INFO_MODIFIED, TEST_RDS_INFO, TEST_VENDOR_INFO);
+ verifyChunkListPurge(programListChunks, /* purge= */ true);
+ verifyChunkListComplete(programListChunks, /* complete= */ false);
+ verifyChunkListModified(programListChunks, maxNumModifiedPerChunk, TEST_FM_INFO_MODIFIED,
+ TEST_RDS_INFO, TEST_VENDOR_INFO);
+ verifyChunkListRemoved(programListChunks, maxNumRemovedPerChunk);
+ }
+
+ @Test
+ public void filterAndApplyChunk_withNonPurgingCompleteChunk() throws RemoteException {
+ ProgramInfoCache cache = new ProgramInfoCache(/* filter= */ null,
+ /* complete= */ false, TEST_FM_INFO, TEST_RDS_INFO, TEST_AM_INFO, TEST_DAB_INFO);
+ ProgramList.Chunk chunk = AidlTestUtils.makeChunk(/* purge= */ false, /* complete= */ true,
+ List.of(TEST_FM_INFO_MODIFIED, TEST_VENDOR_INFO),
+ List.of(TEST_RDS_PI_ID, TEST_AM_FREQUENCY_ID, TEST_DAB_DMB_SID_EXT_ID));
+ int maxNumModifiedPerChunk = 2;
+ int maxNumRemovedPerChunk = 2;
+
+ List<ProgramList.Chunk> programListChunks = cache.filterAndApplyChunkInternal(chunk,
+ maxNumModifiedPerChunk, maxNumRemovedPerChunk);
+
+ expect.withMessage("Program cache applied with purge-enabled complete chunk")
+ .that(cache.toProgramInfoList())
+ .containsExactly(TEST_FM_INFO_MODIFIED, TEST_VENDOR_INFO);
+ verifyChunkListPurge(programListChunks, /* purge= */ false);
+ verifyChunkListComplete(programListChunks, /* complete= */ true);
+ verifyChunkListModified(programListChunks, maxNumModifiedPerChunk, TEST_FM_INFO_MODIFIED,
+ TEST_VENDOR_INFO);
+ verifyChunkListRemoved(programListChunks, maxNumRemovedPerChunk, TEST_RDS_PI_ID,
+ TEST_AM_FREQUENCY_ID, TEST_DAB_DMB_SID_EXT_ID);
+ }
+
+ private void verifyChunkListPurge(List<ProgramList.Chunk> chunks, boolean purge) {
+ if (chunks.isEmpty()) {
+ return;
+ }
+ for (int i = 0; i < chunks.size(); i++) {
+ ProgramList.Chunk chunk = chunks.get(i);
+ boolean expectedPurge = (i == 0 && purge);
+
+ expect.withMessage("Purge for chunk %s", i)
+ .that(chunk.isPurge()).isEqualTo(expectedPurge);
+ }
+ }
+
+ private void verifyChunkListComplete(List<ProgramList.Chunk> chunks, boolean complete) {
+ if (chunks.isEmpty()) {
+ return;
+ }
+ for (int i = 0; i < chunks.size(); i++) {
+ ProgramList.Chunk chunk = chunks.get(i);
+ boolean expectedComplete = (i == chunks.size() - 1 && complete);
+
+ expect.withMessage("Purge for chunk %s", i)
+ .that(chunk.isComplete()).isEqualTo(expectedComplete);
+ }
+ }
+
+ private void verifyChunkListModified(List<ProgramList.Chunk> chunks,
+ int maxModifiedPerChunk, RadioManager.ProgramInfo... expectedProgramInfos) {
+ if (chunks.isEmpty()) {
+ expect.withMessage("Empty program info list")
+ .that(expectedProgramInfos.length).isEqualTo(0);
+ return;
+ }
+
+ ArraySet<RadioManager.ProgramInfo> actualSet = new ArraySet<>();
+ for (int i = 0; i < chunks.size(); i++) {
+ Set<RadioManager.ProgramInfo> chunkModified = chunks.get(i).getModified();
+ actualSet.addAll(chunkModified);
+
+ expect.withMessage("Chunk %s modified program info array size", i)
+ .that(chunkModified.size()).isAtMost(maxModifiedPerChunk);
+ }
+ expect.withMessage("Program info items")
+ .that(actualSet).containsExactlyElementsIn(expectedProgramInfos);
+ }
+
+ private void verifyChunkListRemoved(List<ProgramList.Chunk> chunks,
+ int maxRemovedPerChunk, ProgramSelector.Identifier... expectedIdentifiers) {
+ if (chunks.isEmpty()) {
+ expect.withMessage("Empty program info list")
+ .that(expectedIdentifiers.length).isEqualTo(0);
+ return;
+ }
+
+ ArraySet<ProgramSelector.Identifier> actualSet = new ArraySet<>();
+ for (int i = 0; i < chunks.size(); i++) {
+ Set<ProgramSelector.Identifier> chunkRemoved = chunks.get(i).getRemoved();
+ actualSet.addAll(chunkRemoved);
+
+ expect.withMessage("Chunk %s removed identifier array size ", i)
+ .that(chunkRemoved.size()).isAtMost(maxRemovedPerChunk);
+ }
+ expect.withMessage("Removed identifier items")
+ .that(actualSet).containsExactlyElementsIn(expectedIdentifiers);
+ }
+}
diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java
index d7723ac..464ecb2 100644
--- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java
+++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java
@@ -37,7 +37,9 @@
import android.hardware.broadcastradio.IBroadcastRadio;
import android.hardware.broadcastradio.ITunerCallback;
import android.hardware.broadcastradio.IdentifierType;
+import android.hardware.broadcastradio.ProgramFilter;
import android.hardware.broadcastradio.ProgramInfo;
+import android.hardware.broadcastradio.ProgramListChunk;
import android.hardware.broadcastradio.Result;
import android.hardware.broadcastradio.VendorKeyValue;
import android.hardware.radio.ProgramList;
@@ -61,8 +63,10 @@
import org.mockito.Mock;
import org.mockito.verification.VerificationWithTimeout;
+import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import java.util.Set;
/**
* Tests for AIDL HAL TunerSession.
@@ -72,7 +76,7 @@
private static final int TARGET_SDK_VERSION = Build.VERSION_CODES.CUR_DEVELOPMENT;
private static final VerificationWithTimeout CALLBACK_TIMEOUT =
timeout(/* millis= */ 200);
- private static final int SIGNAL_QUALITY = 1;
+ private static final int SIGNAL_QUALITY = 90;
private static final long AM_FM_FREQUENCY_SPACING = 500;
private static final long[] AM_FM_FREQUENCY_LIST = {97_500, 98_100, 99_100};
private static final RadioManager.FmBandDescriptor FM_BAND_DESCRIPTOR =
@@ -84,6 +88,27 @@
new RadioManager.FmBandConfig(FM_BAND_DESCRIPTOR);
private static final int UNSUPPORTED_CONFIG_FLAG = 0;
+ private static final ProgramSelector.Identifier TEST_FM_FREQUENCY_ID =
+ new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY,
+ /* value= */ 88_500);
+ private static final ProgramSelector.Identifier TEST_RDS_PI_ID =
+ new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_RDS_PI,
+ /* value= */ 15_019);
+
+ private static final RadioManager.ProgramInfo TEST_FM_INFO = AidlTestUtils.makeProgramInfo(
+ AidlTestUtils.makeProgramSelector(ProgramSelector.PROGRAM_TYPE_FM,
+ TEST_FM_FREQUENCY_ID), TEST_FM_FREQUENCY_ID, TEST_FM_FREQUENCY_ID,
+ SIGNAL_QUALITY);
+ private static final RadioManager.ProgramInfo TEST_FM_INFO_MODIFIED =
+ AidlTestUtils.makeProgramInfo(AidlTestUtils.makeProgramSelector(
+ ProgramSelector.PROGRAM_TYPE_FM, TEST_FM_FREQUENCY_ID), TEST_FM_FREQUENCY_ID,
+ TEST_FM_FREQUENCY_ID, /* signalQuality= */ 100);
+ private static final RadioManager.ProgramInfo TEST_RDS_INFO = AidlTestUtils.makeProgramInfo(
+ AidlTestUtils.makeProgramSelector(ProgramSelector.PROGRAM_TYPE_FM, TEST_RDS_PI_ID),
+ TEST_RDS_PI_ID, new ProgramSelector.Identifier(
+ ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY, /* value= */ 89_500),
+ SIGNAL_QUALITY);
+
// Mocks
@Mock private IBroadcastRadio mBroadcastRadioMock;
private android.hardware.radio.ITunerCallback[] mAidlTunerCallbackMocks;
@@ -393,7 +418,7 @@
}
@Test
- public void tune_withHalHasUnknownError_fails() throws Exception {
+ public void tune_withUnknownErrorFromHal_fails() throws Exception {
openAidlClients(/* numClients= */ 1);
ProgramSelector sel = AidlTestUtils.makeFmSelector(AM_FM_FREQUENCY_LIST[1]);
doThrow(new ServiceSpecificException(Result.UNKNOWN_ERROR))
@@ -403,7 +428,7 @@
mTunerSessions[0].tune(sel);
});
- assertWithMessage("Exception for tuning when HAL has unknown error")
+ assertWithMessage("Unknown error HAL exception when tuning")
.that(thrown).hasMessageThat().contains("UNKNOWN_ERROR");
}
@@ -536,7 +561,7 @@
}
@Test
- public void seek_withHalHasInternalError_fails() throws Exception {
+ public void seek_withInternalErrorFromHal_fails() throws Exception {
openAidlClients(/* numClients= */ 1);
doThrow(new ServiceSpecificException(Result.INTERNAL_ERROR))
.when(mBroadcastRadioMock).seek(anyBoolean(), anyBoolean());
@@ -545,7 +570,7 @@
mTunerSessions[0].seek(/* directionDown= */ true, /* skipSubChannel= */ false);
});
- assertWithMessage("Exception for seeking when HAL has internal error")
+ assertWithMessage("Internal error HAL exception when seeking")
.that(thrown).hasMessageThat().contains("INTERNAL_ERROR");
}
@@ -644,11 +669,276 @@
}
@Test
+ public void startProgramListUpdates_withEmptyFilter() throws Exception {
+ openAidlClients(/* numClients= */ 1);
+ ProgramList.Filter filter = new ProgramList.Filter(new ArraySet<>(), new ArraySet<>(),
+ /* includeCategories= */ true, /* excludeModifications= */ false);
+ ProgramFilter halFilter = ConversionUtils.filterToHalProgramFilter(filter);
+ List<RadioManager.ProgramInfo> modified = List.of(TEST_FM_INFO, TEST_RDS_INFO);
+ List<ProgramSelector.Identifier> removed = new ArrayList<>();
+ ProgramListChunk halProgramList = AidlTestUtils.makeHalChunk(/* purge= */ true,
+ /* complete= */ true, modified, removed);
+ ProgramList.Chunk expectedProgramList =
+ AidlTestUtils.makeChunk(/* purge= */ true, /* complete= */ true, modified, removed);
+
+ mTunerSessions[0].startProgramListUpdates(filter);
+ mHalTunerCallback.onProgramListUpdated(halProgramList);
+
+ verify(mBroadcastRadioMock).startProgramListUpdates(halFilter);
+ verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT)
+ .onProgramListUpdated(expectedProgramList);
+ }
+
+ @Test
+ public void startProgramListUpdates_withCallbackCalledForMultipleTimes() throws Exception {
+ openAidlClients(/* numClients= */ 1);
+ ProgramList.Filter filter = new ProgramList.Filter(new ArraySet<>(), new ArraySet<>(),
+ /* includeCategories= */ true, /* excludeModifications= */ false);
+ mTunerSessions[0].startProgramListUpdates(filter);
+ mHalTunerCallback.onProgramListUpdated(AidlTestUtils.makeHalChunk(/* purge= */ true,
+ /* complete= */ true, List.of(TEST_FM_INFO, TEST_RDS_INFO), new ArrayList<>()));
+ verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT).onProgramListUpdated(
+ AidlTestUtils.makeChunk(/* purge= */ true, /* complete= */ true,
+ List.of(TEST_FM_INFO, TEST_RDS_INFO), new ArrayList<>()));
+
+ mHalTunerCallback.onProgramListUpdated(AidlTestUtils.makeHalChunk(/* purge= */ false,
+ /* complete= */ true, List.of(TEST_FM_INFO_MODIFIED), List.of(TEST_RDS_PI_ID)));
+
+ verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT).onProgramListUpdated(
+ AidlTestUtils.makeChunk(/* purge= */ false, /* complete= */ true,
+ List.of(TEST_FM_INFO_MODIFIED), List.of(TEST_RDS_PI_ID)));
+ }
+
+ @Test
+ public void startProgramListUpdates_withTheSameFilterForMultipleTimes() throws Exception {
+ openAidlClients(/* numClients= */ 1);
+ ProgramList.Filter filter = new ProgramList.Filter(new ArraySet<>(), new ArraySet<>(),
+ /* includeCategories= */ true, /* excludeModifications= */ false);
+ mTunerSessions[0].startProgramListUpdates(filter);
+ mHalTunerCallback.onProgramListUpdated(AidlTestUtils.makeHalChunk(/* purge= */ true,
+ /* complete= */ true, List.of(TEST_FM_INFO, TEST_RDS_INFO), new ArrayList<>()));
+ verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT).onProgramListUpdated(
+ AidlTestUtils.makeChunk(/* purge= */ true, /* complete= */ true,
+ List.of(TEST_FM_INFO, TEST_RDS_INFO), new ArrayList<>()));
+ mHalTunerCallback.onProgramListUpdated(AidlTestUtils.makeHalChunk(/* purge= */ false,
+ /* complete= */ true, List.of(TEST_FM_INFO_MODIFIED), List.of(TEST_RDS_PI_ID)));
+ verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT).onProgramListUpdated(
+ AidlTestUtils.makeChunk(/* purge= */ false, /* complete= */ true,
+ List.of(TEST_FM_INFO_MODIFIED), List.of(TEST_RDS_PI_ID)));
+
+ mTunerSessions[0].startProgramListUpdates(filter);
+
+ verify(mBroadcastRadioMock).startProgramListUpdates(any());
+ verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT).onProgramListUpdated(
+ AidlTestUtils.makeChunk(/* purge= */ true, /* complete= */ true,
+ List.of(TEST_FM_INFO_MODIFIED), new ArrayList<>()));
+ }
+
+ @Test
+ public void startProgramListUpdates_withNullFilter() throws Exception {
+ openAidlClients(/* numClients= */ 1);
+
+ mTunerSessions[0].startProgramListUpdates(/* filter= */ null);
+ mHalTunerCallback.onProgramListUpdated(AidlTestUtils.makeHalChunk(/* purge= */ true,
+ /* complete= */ true, List.of(TEST_FM_INFO, TEST_RDS_INFO), new ArrayList<>()));
+
+ verify(mBroadcastRadioMock).startProgramListUpdates(any());
+ verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT).onProgramListUpdated(
+ AidlTestUtils.makeChunk(/* purge= */ true, /* complete= */ true,
+ List.of(TEST_FM_INFO, TEST_RDS_INFO), new ArrayList<>()));
+
+ mHalTunerCallback.onProgramListUpdated(AidlTestUtils.makeHalChunk(/* purge= */ false,
+ /* complete= */ true, List.of(TEST_FM_INFO_MODIFIED), List.of(TEST_RDS_PI_ID)));
+
+ verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT).onProgramListUpdated(
+ AidlTestUtils.makeChunk(/* purge= */ false, /* complete= */ true,
+ List.of(TEST_FM_INFO_MODIFIED), List.of(TEST_RDS_PI_ID)));
+ }
+
+ @Test
+ public void startProgramListUpdates_withIdFilter() throws Exception {
+ openAidlClients(/* numClients= */ 1);
+ ProgramList.Filter idFilter = new ProgramList.Filter(new ArraySet<>(),
+ Set.of(TEST_RDS_PI_ID), /* includeCategories= */ true,
+ /* excludeModifications= */ true);
+ ProgramFilter halFilter = ConversionUtils.filterToHalProgramFilter(idFilter);
+
+ mTunerSessions[0].startProgramListUpdates(idFilter);
+ mHalTunerCallback.onProgramListUpdated(AidlTestUtils.makeHalChunk(/* purge= */ false,
+ /* complete= */ true, List.of(TEST_RDS_INFO), new ArrayList<>()));
+
+ verify(mBroadcastRadioMock).startProgramListUpdates(halFilter);
+ verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT).onProgramListUpdated(
+ AidlTestUtils.makeChunk(/* purge= */ false, /* complete= */ true,
+ List.of(TEST_RDS_INFO), new ArrayList<>()));
+
+ mHalTunerCallback.onProgramListUpdated(AidlTestUtils.makeHalChunk(/* purge= */ false,
+ /* complete= */ true, List.of(TEST_FM_INFO), new ArrayList<>()));
+
+ verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT).onProgramListUpdated(any());
+ }
+
+ @Test
+ public void startProgramListUpdates_withFilterExcludingModifications() throws Exception {
+ openAidlClients(/* numClients= */ 1);
+ ProgramList.Filter filterExcludingModifications = new ProgramList.Filter(
+ Set.of(ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY), new ArraySet<>(),
+ /* includeCategories= */ true, /* excludeModifications= */ true);
+ ProgramFilter halFilter =
+ ConversionUtils.filterToHalProgramFilter(filterExcludingModifications);
+
+ mTunerSessions[0].startProgramListUpdates(filterExcludingModifications);
+ mHalTunerCallback.onProgramListUpdated(AidlTestUtils.makeHalChunk(/* purge= */ false,
+ /* complete= */ true, List.of(TEST_FM_INFO), new ArrayList<>()));
+
+ verify(mBroadcastRadioMock).startProgramListUpdates(halFilter);
+ verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT).onProgramListUpdated(
+ AidlTestUtils.makeChunk(/* purge= */ false, /* complete= */ true,
+ List.of(TEST_FM_INFO), new ArrayList<>()));
+
+ mHalTunerCallback.onProgramListUpdated(AidlTestUtils.makeHalChunk(/* purge= */ false,
+ /* complete= */ true, List.of(TEST_FM_INFO_MODIFIED), new ArrayList<>()));
+
+ verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT).onProgramListUpdated(any());
+ }
+
+ @Test
+ public void startProgramListUpdates_withFilterIncludingModifications() throws Exception {
+ openAidlClients(/* numClients= */ 1);
+ ProgramList.Filter filterIncludingModifications = new ProgramList.Filter(
+ Set.of(ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY), new ArraySet<>(),
+ /* includeCategories= */ true, /* excludeModifications= */ false);
+ ProgramFilter halFilter =
+ ConversionUtils.filterToHalProgramFilter(filterIncludingModifications);
+
+ mTunerSessions[0].startProgramListUpdates(filterIncludingModifications);
+ mHalTunerCallback.onProgramListUpdated(AidlTestUtils.makeHalChunk(/* purge= */ false,
+ /* complete= */ true, List.of(TEST_FM_INFO), new ArrayList<>()));
+
+ verify(mBroadcastRadioMock).startProgramListUpdates(halFilter);
+ verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT).onProgramListUpdated(
+ AidlTestUtils.makeChunk(/* purge= */ false, /* complete= */ true,
+ List.of(TEST_FM_INFO), new ArrayList<>()));
+
+ mHalTunerCallback.onProgramListUpdated(AidlTestUtils.makeHalChunk(/* purge= */ false,
+ /* complete= */ true, List.of(TEST_FM_INFO_MODIFIED), new ArrayList<>()));
+
+ verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT).onProgramListUpdated(
+ AidlTestUtils.makeChunk(/* purge= */ false, /* complete= */ true,
+ List.of(TEST_FM_INFO_MODIFIED), new ArrayList<>()));
+ }
+
+ @Test
+ public void onProgramListUpdated_afterSessionClosed_doesNotUpdates() throws Exception {
+ openAidlClients(/* numClients= */ 1);
+ ProgramList.Filter filter = new ProgramList.Filter(new ArraySet<>(), new ArraySet<>(),
+ /* includeCategories= */ true, /* excludeModifications= */ false);
+ mTunerSessions[0].startProgramListUpdates(filter);
+
+ mTunerSessions[0].close();
+
+ verify(mBroadcastRadioMock).stopProgramListUpdates();
+
+ mHalTunerCallback.onProgramListUpdated(AidlTestUtils.makeHalChunk(/* purge= */ false,
+ /* complete= */ true, List.of(TEST_FM_INFO), new ArrayList<>()));
+
+ verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT.times(0)).onProgramListUpdated(any());
+ }
+
+ @Test
+ public void startProgramListUpdates_forMultipleSessions() throws Exception {
+ int numSessions = 3;
+ openAidlClients(numSessions);
+ ProgramList.Filter fmIdFilter = new ProgramList.Filter(new ArraySet<>(),
+ Set.of(TEST_FM_FREQUENCY_ID), /* includeCategories= */ false,
+ /* excludeModifications= */ true);
+ ProgramList.Filter filterExcludingCategories = new ProgramList.Filter(new ArraySet<>(),
+ new ArraySet<>(), /* includeCategories= */ true,
+ /* excludeModifications= */ true);
+ ProgramList.Filter rdsTypeFilter = new ProgramList.Filter(
+ Set.of(ProgramSelector.IDENTIFIER_TYPE_RDS_PI), new ArraySet<>(),
+ /* includeCategories= */ true, /* excludeModifications= */ false);
+
+ mTunerSessions[0].startProgramListUpdates(fmIdFilter);
+
+ ProgramFilter halFilter = ConversionUtils.filterToHalProgramFilter(fmIdFilter);
+ verify(mBroadcastRadioMock).startProgramListUpdates(halFilter);
+
+ mTunerSessions[1].startProgramListUpdates(filterExcludingCategories);
+
+ halFilter.identifiers = new android.hardware.broadcastradio.ProgramIdentifier[]{};
+ halFilter.includeCategories = true;
+ verify(mBroadcastRadioMock).startProgramListUpdates(halFilter);
+
+ mTunerSessions[2].startProgramListUpdates(rdsTypeFilter);
+
+ halFilter.excludeModifications = false;
+ verify(mBroadcastRadioMock).startProgramListUpdates(halFilter);
+ }
+
+ @Test
+ public void onProgramListUpdated_forMultipleSessions() throws Exception {
+ int numSessions = 3;
+ openAidlClients(numSessions);
+ List<ProgramList.Filter> filters = List.of(new ProgramList.Filter(
+ Set.of(ProgramSelector.IDENTIFIER_TYPE_RDS_PI), new ArraySet<>(),
+ /* includeCategories= */ true, /* excludeModifications= */ false),
+ new ProgramList.Filter(new ArraySet<>(), Set.of(TEST_FM_FREQUENCY_ID),
+ /* includeCategories= */ false, /* excludeModifications= */ true),
+ new ProgramList.Filter(new ArraySet<>(), new ArraySet<>(),
+ /* includeCategories= */ true, /* excludeModifications= */ true));
+
+ for (int index = 0; index < numSessions; index++) {
+ mTunerSessions[index].startProgramListUpdates(filters.get(index));
+ }
+
+ mHalTunerCallback.onProgramListUpdated(AidlTestUtils.makeHalChunk(/* purge= */ false,
+ /* complete= */ true, List.of(TEST_FM_INFO, TEST_RDS_INFO), new ArrayList<>()));
+
+ verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT)
+ .onProgramListUpdated(AidlTestUtils.makeChunk(/* purge= */ false,
+ /* complete= */ true, List.of(TEST_RDS_INFO), new ArrayList<>()));
+ verify(mAidlTunerCallbackMocks[1], CALLBACK_TIMEOUT)
+ .onProgramListUpdated(AidlTestUtils.makeChunk(/* purge= */ false,
+ /* complete= */ true, List.of(TEST_FM_INFO), new ArrayList<>()));
+ verify(mAidlTunerCallbackMocks[2], CALLBACK_TIMEOUT)
+ .onProgramListUpdated(AidlTestUtils.makeChunk(/* purge= */ false,
+ /* complete= */ true, List.of(TEST_RDS_INFO, TEST_FM_INFO),
+ new ArrayList<>()));
+ }
+
+ @Test
+ public void startProgramListUpdates_forNonCurrentUser_doesNotStartUpdates() throws Exception {
+ openAidlClients(/* numClients= */ 1);
+ ProgramList.Filter filter = new ProgramList.Filter(new ArraySet<>(), new ArraySet<>(),
+ /* includeCategories= */ true, /* excludeModifications= */ false);
+ doReturn(false).when(() -> RadioServiceUserController.isCurrentOrSystemUser());
+
+ mTunerSessions[0].startProgramListUpdates(filter);
+
+ verify(mBroadcastRadioMock, never()).startProgramListUpdates(any());
+ }
+
+ @Test
+ public void startProgramListUpdates_withUnknownErrorFromHal_fails() throws Exception {
+ openAidlClients(/* numClients= */ 1);
+ doThrow(new ServiceSpecificException(Result.UNKNOWN_ERROR))
+ .when(mBroadcastRadioMock).startProgramListUpdates(any());
+
+ ParcelableException thrown = assertThrows(ParcelableException.class, () -> {
+ mTunerSessions[0].startProgramListUpdates(/* filter= */ null);
+ });
+
+ assertWithMessage("Unknown error HAL exception when updating program list")
+ .that(thrown).hasMessageThat().contains("UNKNOWN_ERROR");
+ }
+
+ @Test
public void stopProgramListUpdates() throws Exception {
openAidlClients(/* numClients= */ 1);
- ProgramList.Filter aidlFilter = new ProgramList.Filter(new ArraySet<>(), new ArraySet<>(),
+ ProgramList.Filter filter = new ProgramList.Filter(new ArraySet<>(), new ArraySet<>(),
/* includeCategories= */ true, /* excludeModifications= */ false);
- mTunerSessions[0].startProgramListUpdates(aidlFilter);
+ mTunerSessions[0].startProgramListUpdates(filter);
mTunerSessions[0].stopProgramListUpdates();
@@ -658,9 +948,9 @@
@Test
public void stopProgramListUpdates_forNonCurrentUser_doesNotStopUpdates() throws Exception {
openAidlClients(/* numClients= */ 1);
- ProgramList.Filter aidlFilter = new ProgramList.Filter(new ArraySet<>(), new ArraySet<>(),
+ ProgramList.Filter filter = new ProgramList.Filter(new ArraySet<>(), new ArraySet<>(),
/* includeCategories= */ true, /* excludeModifications= */ false);
- mTunerSessions[0].startProgramListUpdates(aidlFilter);
+ mTunerSessions[0].startProgramListUpdates(filter);
doReturn(false).when(() -> RadioServiceUserController.isCurrentOrSystemUser());
mTunerSessions[0].stopProgramListUpdates();
diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/TunerSessionHidlTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/TunerSessionHidlTest.java
index ea9a846..3815008 100644
--- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/TunerSessionHidlTest.java
+++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/TunerSessionHidlTest.java
@@ -373,7 +373,7 @@
}
@Test
- public void tune_withHalHasUnknownError_fails() throws Exception {
+ public void tune_withUnknownErrorFromHal_fails() throws Exception {
openAidlClients(/* numClients= */ 1);
ProgramSelector sel = TestUtils.makeFmSelector(AM_FM_FREQUENCY_LIST[1]);
doAnswer(invocation -> Result.UNKNOWN_ERROR).when(mHalTunerSessionMock).tune(any());
@@ -382,7 +382,7 @@
mTunerSessions[0].tune(sel);
});
- assertWithMessage("Exception for tuning when HAL has unknown error")
+ assertWithMessage("Unknown error HAL exception when tuning")
.that(thrown).hasMessageThat().contains(Result.toString(Result.UNKNOWN_ERROR));
}
@@ -513,7 +513,7 @@
}
@Test
- public void seek_withHalHasInternalError_fails() throws Exception {
+ public void seek_withInternalErrorFromHal_fails() throws Exception {
openAidlClients(/* numClients= */ 1);
doAnswer(invocation -> Result.INTERNAL_ERROR).when(mHalTunerSessionMock)
.scan(anyBoolean(), anyBoolean());
@@ -522,7 +522,7 @@
mTunerSessions[0].seek(/* directionDown= */ true, /* skipSubChannel= */ false);
});
- assertWithMessage("Exception for seeking when HAL has internal error")
+ assertWithMessage("Internal error HAL exception when seeking")
.that(thrown).hasMessageThat().contains(Result.toString(Result.INTERNAL_ERROR));
}
@@ -633,6 +633,32 @@
}
@Test
+ public void startProgramListUpdates_forNonCurrentUser_doesNotStartUpdates() throws Exception {
+ openAidlClients(/* numClients= */ 1);
+ ProgramList.Filter filter = new ProgramList.Filter(new ArraySet<>(), new ArraySet<>(),
+ /* includeCategories= */ true, /* excludeModifications= */ false);
+ doReturn(false).when(() -> RadioServiceUserController.isCurrentOrSystemUser());
+
+ mTunerSessions[0].startProgramListUpdates(filter);
+
+ verify(mHalTunerSessionMock, never()).startProgramListUpdates(any());
+ }
+
+ @Test
+ public void startProgramListUpdates_withUnknownErrorFromHal_fails() throws Exception {
+ openAidlClients(/* numClients= */ 1);
+ doAnswer(invocation -> Result.UNKNOWN_ERROR).when(mHalTunerSessionMock)
+ .startProgramListUpdates(any());
+
+ ParcelableException thrown = assertThrows(ParcelableException.class, () -> {
+ mTunerSessions[0].startProgramListUpdates(/* filter= */ null);
+ });
+
+ assertWithMessage("Unknown error HAL exception when updating program list")
+ .that(thrown).hasMessageThat().contains(Result.toString(Result.UNKNOWN_ERROR));
+ }
+
+ @Test
public void stopProgramListUpdates() throws Exception {
openAidlClients(/* numClients= */ 1);
ProgramList.Filter aidlFilter = new ProgramList.Filter(new ArraySet<>(), new ArraySet<>(),
diff --git a/core/tests/coretests/src/android/companion/virtual/camera/VirtualCameraOutputTest.java b/core/tests/coretests/src/android/companion/virtual/camera/VirtualCameraOutputTest.java
index 694b312..f96d138 100644
--- a/core/tests/coretests/src/android/companion/virtual/camera/VirtualCameraOutputTest.java
+++ b/core/tests/coretests/src/android/companion/virtual/camera/VirtualCameraOutputTest.java
@@ -23,13 +23,16 @@
import android.graphics.PixelFormat;
import android.hardware.camera2.params.InputConfiguration;
import android.os.ParcelFileDescriptor;
+import android.platform.test.annotations.Presubmit;
import android.util.Log;
import androidx.annotation.NonNull;
+import androidx.test.runner.AndroidJUnit4;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.junit.runner.RunWith;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
@@ -38,6 +41,8 @@
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+@Presubmit
+@RunWith(AndroidJUnit4.class)
public class VirtualCameraOutputTest {
private static final String TAG = "VirtualCameraOutputTest";
diff --git a/core/tests/coretests/src/android/companion/virtual/sensor/VirtualSensorConfigTest.java b/core/tests/coretests/src/android/companion/virtual/sensor/VirtualSensorConfigTest.java
index 11afd04..2a1881e 100644
--- a/core/tests/coretests/src/android/companion/virtual/sensor/VirtualSensorConfigTest.java
+++ b/core/tests/coretests/src/android/companion/virtual/sensor/VirtualSensorConfigTest.java
@@ -26,6 +26,7 @@
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import android.os.Parcel;
+import android.platform.test.annotations.Presubmit;
import androidx.test.runner.AndroidJUnit4;
@@ -42,6 +43,7 @@
import java.time.Duration;
+@Presubmit
@RunWith(AndroidJUnit4.class)
public class VirtualSensorConfigTest {
diff --git a/core/tests/coretests/src/android/companion/virtual/sensor/VirtualSensorEventTest.java b/core/tests/coretests/src/android/companion/virtual/sensor/VirtualSensorEventTest.java
index a9583fd..c260ef9 100644
--- a/core/tests/coretests/src/android/companion/virtual/sensor/VirtualSensorEventTest.java
+++ b/core/tests/coretests/src/android/companion/virtual/sensor/VirtualSensorEventTest.java
@@ -22,12 +22,14 @@
import android.os.Parcel;
import android.os.SystemClock;
+import android.platform.test.annotations.Presubmit;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
+@Presubmit
@RunWith(AndroidJUnit4.class)
public class VirtualSensorEventTest {
diff --git a/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt b/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt
index 625c318..249e246 100644
--- a/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt
+++ b/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt
@@ -16,6 +16,8 @@
package android.content.res
+
+import android.platform.test.annotations.Presubmit
import androidx.core.util.forEach
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
@@ -27,6 +29,7 @@
import org.junit.Test
import org.junit.runner.RunWith
+@Presubmit
@RunWith(AndroidJUnit4::class)
class FontScaleConverterFactoryTest {
@@ -79,10 +82,10 @@
@LargeTest
@Test
fun allFeasibleScalesAndConversionsDoNotCrash() {
- generateSequenceOfFractions(-10000f..10000f, step = 0.01f)
+ generateSequenceOfFractions(-10f..10f, step = 0.01f)
.mapNotNull{ FontScaleConverterFactory.forScale(it) }
.flatMap{ table ->
- generateSequenceOfFractions(-10000f..10000f, step = 0.01f)
+ generateSequenceOfFractions(-2000f..2000f, step = 0.01f)
.map{ Pair(table, it) }
}
.forEach { (table, sp) ->
diff --git a/core/tests/coretests/src/android/content/res/FontScaleConverterTest.kt b/core/tests/coretests/src/android/content/res/FontScaleConverterTest.kt
index e9f850e..bfa8c9a 100644
--- a/core/tests/coretests/src/android/content/res/FontScaleConverterTest.kt
+++ b/core/tests/coretests/src/android/content/res/FontScaleConverterTest.kt
@@ -16,11 +16,13 @@
package android.content.res
+import android.platform.test.annotations.Presubmit
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.google.common.truth.Truth.assertWithMessage
import org.junit.Test
import org.junit.runner.RunWith
+@Presubmit
@RunWith(AndroidJUnit4::class)
class FontScaleConverterTest {
diff --git a/core/tests/coretests/src/android/internal/os/anr/AnrLatencyTrackerTests.java b/core/tests/coretests/src/android/internal/os/anr/AnrLatencyTrackerTests.java
index ebd78b46..4eea076 100644
--- a/core/tests/coretests/src/android/internal/os/anr/AnrLatencyTrackerTests.java
+++ b/core/tests/coretests/src/android/internal/os/anr/AnrLatencyTrackerTests.java
@@ -57,7 +57,9 @@
.thenReturn(158L)
.thenReturn(165L)
.thenReturn(175L)
- .thenReturn(188L);
+ .thenReturn(198L)
+ .thenReturn(203L)
+ .thenReturn(209L);
}
@Test
@@ -109,7 +111,7 @@
mLatencyTracker.close();
assertThat(mLatencyTracker.dumpAsCommaSeparatedArrayWithHeader())
- .isEqualTo("DurationsV1: 50,5,25,8,100,2,3,7,8,15,2,7,13,10,3,4\n\n");
+ .isEqualTo("DurationsV2: 50,5,25,8,115,2,3,7,8,15,2,7,23,10,3,6\n\n");
verify(mLatencyTracker, times(1)).pushAtom();
}
diff --git a/core/tests/coretests/src/android/internal/os/anr/OWNERS b/core/tests/coretests/src/android/internal/os/anr/OWNERS
new file mode 100644
index 0000000..59cc70e
--- /dev/null
+++ b/core/tests/coretests/src/android/internal/os/anr/OWNERS
@@ -0,0 +1 @@
+include /core/java/com/android/internal/os/anr/OWNERS
diff --git a/core/tests/coretests/src/android/util/TypedValueTest.kt b/core/tests/coretests/src/android/util/TypedValueTest.kt
index b020c38..af01447 100644
--- a/core/tests/coretests/src/android/util/TypedValueTest.kt
+++ b/core/tests/coretests/src/android/util/TypedValueTest.kt
@@ -17,6 +17,7 @@
package android.util
import android.content.res.FontScaleConverterFactory
+import android.platform.test.annotations.Presubmit
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
import androidx.test.filters.SmallTest
@@ -30,6 +31,7 @@
import kotlin.math.min
import kotlin.math.roundToInt
+@Presubmit
@RunWith(AndroidJUnit4::class)
class TypedValueTest {
@LargeTest
@@ -223,7 +225,6 @@
metrics.scaledDensity = 0f
listOf(
- TypedValue.COMPLEX_UNIT_PX,
TypedValue.COMPLEX_UNIT_DIP,
TypedValue.COMPLEX_UNIT_SP,
TypedValue.COMPLEX_UNIT_PT,
@@ -257,8 +258,7 @@
TypedValue.COMPLEX_UNIT_MM
)
.forEach { dimenType ->
- // Test for every integer value in the range...
- for (i: Int in -(1 shl 23) until (1 shl 23)) {
+ for (i: Int in -10000 until 10000) {
assertRoundTripIsEqual(i.toFloat(), dimenType, metrics)
assertRoundTripIsEqual(i - .1f, dimenType, metrics)
assertRoundTripIsEqual(i + .5f, dimenType, metrics)
diff --git a/core/tests/coretests/src/android/view/WindowInfoTest.java b/core/tests/coretests/src/android/view/WindowInfoTest.java
index f9e3f43..d927f06 100644
--- a/core/tests/coretests/src/android/view/WindowInfoTest.java
+++ b/core/tests/coretests/src/android/view/WindowInfoTest.java
@@ -28,6 +28,7 @@
import android.app.ActivityTaskManager;
import android.graphics.Matrix;
import android.os.IBinder;
+import android.os.LocaleList;
import android.os.Parcel;
import android.platform.test.annotations.Presubmit;
import android.text.TextUtils;
@@ -41,6 +42,7 @@
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Locale;
/**
* Class for testing {@link WindowInfo}.
@@ -48,6 +50,7 @@
@Presubmit
@RunWith(AndroidJUnit4.class)
public class WindowInfoTest {
+ private static final LocaleList TEST_LOCALES = new LocaleList(Locale.ROOT);
@SmallTest
@Test
@@ -129,6 +132,7 @@
assertTrue(windowinfo.regionInScreen.isEmpty());
assertEquals(windowinfo.mTransformMatrix.length, 9);
assertTrue(windowinfo.mMagnificationSpec.isNop());
+ assertEquals(windowinfo.locales, LocaleList.getEmptyLocaleList());
}
private boolean areWindowsEqual(WindowInfo w1, WindowInfo w2) {
@@ -141,6 +145,7 @@
equality &= w1.mMagnificationSpec.equals(w2.mMagnificationSpec);
equality &= Arrays.equals(w1.mTransformMatrix, w2.mTransformMatrix);
equality &= TextUtils.equals(w1.title, w2.title);
+ equality &= w1.locales.equals(w2.locales);
return equality;
}
@@ -164,5 +169,6 @@
windowInfo.mMagnificationSpec.offsetX = 100f;
windowInfo.mMagnificationSpec.offsetY = 200f;
Matrix.IDENTITY_MATRIX.getValues(windowInfo.mTransformMatrix);
+ windowInfo.locales = TEST_LOCALES;
}
}
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityWindowAttributesTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityWindowAttributesTest.java
index a6abee5..8d1c2e3 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityWindowAttributesTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityWindowAttributesTest.java
@@ -20,6 +20,7 @@
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotSame;
+import android.os.LocaleList;
import android.os.Parcel;
import android.platform.test.annotations.Presubmit;
import android.view.WindowManager;
@@ -30,6 +31,8 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.Locale;
+
/**
* Class for testing {@link AccessibilityWindowAttributes}.
*/
@@ -37,11 +40,13 @@
@RunWith(AndroidJUnit4.class)
public class AccessibilityWindowAttributesTest {
private static final String TEST_WINDOW_TITLE = "test window title";
+ private static final LocaleList TEST_LOCALES = new LocaleList(Locale.ROOT);
@SmallTest
@Test
public void testParceling() {
- final AccessibilityWindowAttributes windowAttributes = createInstance(TEST_WINDOW_TITLE);
+ final AccessibilityWindowAttributes windowAttributes = createInstance(
+ TEST_WINDOW_TITLE, TEST_LOCALES);
Parcel parcel = Parcel.obtain();
windowAttributes.writeToParcel(parcel, 0);
parcel.setDataPosition(0);
@@ -56,14 +61,21 @@
@SmallTest
@Test
public void testNonequality() {
- final AccessibilityWindowAttributes windowAttributes = createInstance(null);
- final AccessibilityWindowAttributes windowAttributes2 = createInstance(TEST_WINDOW_TITLE);
+ final AccessibilityWindowAttributes windowAttributes = createInstance(
+ null, TEST_LOCALES);
+ final AccessibilityWindowAttributes windowAttributes1 = createInstance(
+ TEST_WINDOW_TITLE, TEST_LOCALES);
+ final AccessibilityWindowAttributes windowAttributes2 = createInstance(
+ TEST_WINDOW_TITLE, null);
+ assertNotEquals(windowAttributes, windowAttributes1);
assertNotEquals(windowAttributes, windowAttributes2);
+ assertNotEquals(windowAttributes1, windowAttributes2);
}
- private static AccessibilityWindowAttributes createInstance(String windowTitle) {
+ private static AccessibilityWindowAttributes createInstance(
+ String windowTitle, LocaleList locales) {
final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
layoutParams.accessibilityTitle = windowTitle;
- return new AccessibilityWindowAttributes(layoutParams);
+ return new AccessibilityWindowAttributes(layoutParams, locales);
}
}
diff --git a/core/tests/coretests/src/android/view/autofill/AutofillFeatureFlagsTest.java b/core/tests/coretests/src/android/view/autofill/AutofillFeatureFlagsTest.java
new file mode 100644
index 0000000..e03b722
--- /dev/null
+++ b/core/tests/coretests/src/android/view/autofill/AutofillFeatureFlagsTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.autofill;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.provider.DeviceConfig;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for {@link AutofillFeatureFlags}
+ *
+ * run: atest FrameworksCoreTests:android.view.autofill.AutofillFeatureFlagsTest
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class AutofillFeatureFlagsTest {
+
+ @Test
+ public void testGetFillDialogEnabledHintsEmpty() {
+ setFillDialogHints("");
+ String[] fillDialogHints = AutofillFeatureFlags.getFillDialogEnabledHints();
+ assertThat(fillDialogHints).isEmpty();
+ }
+
+ @Test
+ public void testGetFillDialogEnabledHintsTwoValues() {
+ setFillDialogHints("password:creditCardNumber");
+ String[] fillDialogHints = AutofillFeatureFlags.getFillDialogEnabledHints();
+ assertThat(fillDialogHints.length).isEqualTo(2);
+ assertThat(fillDialogHints[0]).isEqualTo("password");
+ assertThat(fillDialogHints[1]).isEqualTo("creditCardNumber");
+ }
+
+ @Test
+ public void testIsCredentialManagerEnabled() {
+ setCredentialManagerEnabled(false);
+ assertThat(AutofillFeatureFlags.isCredentialManagerEnabled()).isFalse();
+ setCredentialManagerEnabled(true);
+ assertThat(AutofillFeatureFlags.isCredentialManagerEnabled()).isTrue();
+ }
+
+ @Test
+ public void testShouldIgnoreCredentialManagerViews() {
+ setCredentialManagerEnabled(false);
+ setIgnoreCredentialManagerViews(true);
+ // Overall feature is disabled, so we shouldn't ignore views.
+ assertThat(AutofillFeatureFlags.shouldIgnoreCredentialViews()).isFalse();
+ setCredentialManagerEnabled(true);
+ assertThat(AutofillFeatureFlags.shouldIgnoreCredentialViews()).isTrue();
+ }
+
+ private static void setFillDialogHints(String value) {
+ setDeviceConfig(
+ AutofillFeatureFlags.DEVICE_CONFIG_AUTOFILL_DIALOG_HINTS,
+ value);
+ }
+
+ private static void setCredentialManagerEnabled(boolean value) {
+ setDeviceConfig(
+ AutofillFeatureFlags.DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_ENABLED,
+ String.valueOf(value));
+ }
+
+ private static void setIgnoreCredentialManagerViews(boolean value) {
+ setDeviceConfig(
+ AutofillFeatureFlags.DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_IGNORE_VIEWS,
+ String.valueOf(value));
+ }
+
+ private static void setDeviceConfig(String key, String value) {
+ DeviceConfig.setProperty(
+ DeviceConfig.NAMESPACE_AUTOFILL, key, value, /* makeDefault */ false);
+ }
+}
diff --git a/data/etc/com.android.systemui.xml b/data/etc/com.android.systemui.xml
index fc19944..0aad0a8 100644
--- a/data/etc/com.android.systemui.xml
+++ b/data/etc/com.android.systemui.xml
@@ -83,5 +83,6 @@
<permission name="android.permission.READ_SAFETY_CENTER_STATUS" />
<permission name="android.permission.SET_UNRESTRICTED_KEEP_CLEAR_AREAS" />
<permission name="android.permission.READ_SEARCH_INDEXABLES" />
+ <permission name="android.permission.ACCESS_AMBIENT_CONTEXT_EVENT"/>
</privapp-permissions>
</permissions>
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 1070841..d533805 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -454,6 +454,7 @@
<!-- Permission required for hotword detection service CTS tests -->
<permission name="android.permission.MANAGE_HOTWORD_DETECTION" />
<permission name="android.permission.BIND_HOTWORD_DETECTION_SERVICE" />
+ <permission name="android.permission.BIND_VISUAL_QUERY_DETECTION_SERVICE" />
<permission name="android.permission.MANAGE_APP_HIBERNATION"/>
<!-- Permission required for CTS test - ResourceObserverNativeTest -->
<permission name="android.permission.REGISTER_MEDIA_RESOURCE_OBSERVER" />
@@ -500,6 +501,8 @@
<permission name="android.permission.MODIFY_CELL_BROADCASTS" />
<!-- Permission required for CTS test - CtsBroadcastRadioTestCases -->
<permission name="android.permission.ACCESS_BROADCAST_RADIO"/>
+ <!-- Permission required for CTS test - CtsAmbientContextServiceTestCases -->
+ <permission name="android.permission.ACCESS_AMBIENT_CONTEXT_EVENT"/>
</privapp-permissions>
<privapp-permissions package="com.android.statementservice">
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index f0e496f..d35dcab 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -3151,10 +3151,10 @@
* @see #getRunAdvance(char[], int, int, int, int, boolean, int) for more details.
*
* @param text the text to measure. Cannot be null.
- * @param start the index of the start of the range to measure
- * @param end the index + 1 of the end of the range to measure
- * @param contextStart the index of the start of the shaping context
- * @param contextEnd the index + 1 of the end of the shaping context
+ * @param start the start index of the range to measure, inclusive
+ * @param end the end index of the range to measure, exclusive
+ * @param contextStart the start index of the shaping context, inclusive
+ * @param contextEnd the end index of the shaping context, exclusive
* @param isRtl whether the run is in RTL direction
* @param offset index of caret position
* @param advances the array that receives the computed character advances
diff --git a/graphics/java/android/graphics/drawable/LottieDrawable.java b/graphics/java/android/graphics/drawable/LottieDrawable.java
new file mode 100644
index 0000000..c1f1b50
--- /dev/null
+++ b/graphics/java/android/graphics/drawable/LottieDrawable.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics.drawable;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.PixelFormat;
+
+import dalvik.annotation.optimization.FastNative;
+
+import libcore.util.NativeAllocationRegistry;
+
+import java.io.IOException;
+
+/**
+ * {@link Drawable} for drawing Lottie files.
+ *
+ * <p>The framework handles decoding subsequent frames in another thread and
+ * updating when necessary. The drawable will only animate while it is being
+ * displayed.</p>
+ *
+ * @hide
+ */
+@SuppressLint("NotCloseable")
+public class LottieDrawable extends Drawable implements Animatable {
+ private long mNativePtr;
+
+ /**
+ * Create an animation from the provided JSON string
+ * @hide
+ */
+ private LottieDrawable(@NonNull String animationJson) throws IOException {
+ mNativePtr = nCreate(animationJson);
+ if (mNativePtr == 0) {
+ throw new IOException("could not make LottieDrawable from json");
+ }
+
+ final long nativeSize = nNativeByteSize(mNativePtr);
+ NativeAllocationRegistry registry = new NativeAllocationRegistry(
+ LottieDrawable.class.getClassLoader(), nGetNativeFinalizer(), nativeSize);
+ registry.registerNativeAllocation(this, mNativePtr);
+ }
+
+ /**
+ * Factory for LottieDrawable, throws IOException if native Skottie Builder fails to parse
+ */
+ public static LottieDrawable makeLottieDrawable(@NonNull String animationJson)
+ throws IOException {
+ return new LottieDrawable(animationJson);
+ }
+
+
+
+ /**
+ * Draw the current frame to the Canvas.
+ * @hide
+ */
+ @Override
+ public void draw(@NonNull Canvas canvas) {
+ if (mNativePtr == 0) {
+ throw new IllegalStateException("called draw on empty LottieDrawable");
+ }
+
+ nDraw(mNativePtr, canvas.getNativeCanvasWrapper());
+ }
+
+ /**
+ * Start the animation. Needs to be called before draw calls.
+ * @hide
+ */
+ @Override
+ public void start() {
+ if (mNativePtr == 0) {
+ throw new IllegalStateException("called start on empty LottieDrawable");
+ }
+
+ if (nStart(mNativePtr)) {
+ invalidateSelf();
+ }
+ }
+
+ /**
+ * Stops the animation playback. Does not release anything.
+ * @hide
+ */
+ @Override
+ public void stop() {
+ if (mNativePtr == 0) {
+ throw new IllegalStateException("called stop on empty LottieDrawable");
+ }
+ nStop(mNativePtr);
+ }
+
+ /**
+ * Return whether the animation is currently running.
+ */
+ @Override
+ public boolean isRunning() {
+ if (mNativePtr == 0) {
+ throw new IllegalStateException("called isRunning on empty LottieDrawable");
+ }
+ return nIsRunning(mNativePtr);
+ }
+
+ @Override
+ public int getOpacity() {
+ // We assume translucency to avoid checking each pixel.
+ return PixelFormat.TRANSLUCENT;
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ //TODO
+ }
+
+ @Override
+ public void setColorFilter(@Nullable ColorFilter colorFilter) {
+ //TODO
+ }
+
+ private static native long nCreate(String json);
+ private static native void nDraw(long nativeInstance, long nativeCanvas);
+ @FastNative
+ private static native long nGetNativeFinalizer();
+ @FastNative
+ private static native long nNativeByteSize(long nativeInstance);
+ @FastNative
+ private static native boolean nIsRunning(long nativeInstance);
+ @FastNative
+ private static native boolean nStart(long nativeInstance);
+ @FastNative
+ private static native boolean nStop(long nativeInstance);
+
+}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
index 07d0d96..ee8ec1d 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
@@ -239,6 +239,11 @@
void setAdjacentTaskFragments(@NonNull WindowContainerTransaction wct,
@NonNull IBinder primary, @Nullable IBinder secondary, @Nullable SplitRule splitRule) {
+ if (secondary == null) {
+ wct.clearAdjacentTaskFragments(primary);
+ return;
+ }
+
WindowContainerTransaction.TaskFragmentAdjacentParams adjacentParams = null;
final boolean finishSecondaryWithPrimary =
splitRule != null && SplitContainer.shouldFinishSecondaryWithPrimary(splitRule);
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java
index 07d0158..c5d932e 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java
@@ -79,6 +79,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import androidx.window.common.DeviceStateManagerFoldingFeatureProducer;
+import androidx.window.extensions.core.util.function.Function;
import androidx.window.extensions.layout.WindowLayoutComponentImpl;
import androidx.window.extensions.layout.WindowLayoutInfo;
@@ -563,10 +564,10 @@
SplitAttributes.SplitType.RatioSplitType.splitEqually()
)
).build();
+ final Function<SplitAttributesCalculatorParams, SplitAttributes> calculator =
+ params -> splitAttributes;
- mController.setSplitAttributesCalculator(params -> {
- return splitAttributes;
- });
+ mController.setSplitAttributesCalculator(calculator);
assertEquals(splitAttributes, mPresenter.computeSplitAttributes(taskProperties,
splitPairRule, null /* minDimensionsPair */));
diff --git a/libs/WindowManager/Jetpack/window-extensions-release.aar b/libs/WindowManager/Jetpack/window-extensions-release.aar
index 5de5365..cddbf469 100644
--- a/libs/WindowManager/Jetpack/window-extensions-release.aar
+++ b/libs/WindowManager/Jetpack/window-extensions-release.aar
Binary files differ
diff --git a/libs/WindowManager/Shell/res/drawable/caption_decor_title.xml b/libs/WindowManager/Shell/res/drawable/caption_decor_title.xml
new file mode 100644
index 0000000..6114ad6
--- /dev/null
+++ b/libs/WindowManager/Shell/res/drawable/caption_decor_title.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<shape android:shape="rectangle"
+ android:tintMode="multiply"
+ android:tint="@color/decor_title_color"
+ xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="@android:color/white" />
+</shape>
diff --git a/libs/WindowManager/Shell/res/drawable/decor_minimize_button_dark.xml b/libs/WindowManager/Shell/res/drawable/decor_minimize_button_dark.xml
index b7ff96e..91edbf1 100644
--- a/libs/WindowManager/Shell/res/drawable/decor_minimize_button_dark.xml
+++ b/libs/WindowManager/Shell/res/drawable/decor_minimize_button_dark.xml
@@ -14,10 +14,10 @@
~ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24"
+ android:width="32.0dp"
+ android:height="32.0dp"
+ android:viewportWidth="32.0"
+ android:viewportHeight="32.0"
android:tint="@color/decor_button_dark_color">
<path
android:fillColor="@android:color/white" android:pathData="M6,21V19H18V21Z"/>
diff --git a/libs/WindowManager/Shell/res/layout/caption_window_decor.xml b/libs/WindowManager/Shell/res/layout/caption_window_decor.xml
new file mode 100644
index 0000000..f3d2198
--- /dev/null
+++ b/libs/WindowManager/Shell/res/layout/caption_window_decor.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<com.android.wm.shell.windowdecor.WindowDecorLinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/caption"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="end"
+ android:background="@drawable/caption_decor_title">
+ <Button
+ style="@style/CaptionButtonStyle"
+ android:id="@+id/back_button"
+ android:layout_gravity="center_vertical|end"
+ android:contentDescription="@string/back_button_text"
+ android:background="@drawable/decor_back_button_dark"
+ android:duplicateParentState="true"/>
+ <Space
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:elevation="2dp"/>
+ <Button
+ style="@style/CaptionButtonStyle"
+ android:id="@+id/minimize_window"
+ android:layout_gravity="center_vertical|end"
+ android:contentDescription="@string/minimize_button_text"
+ android:background="@drawable/decor_minimize_button_dark"
+ android:duplicateParentState="true"/>
+ <Button
+ style="@style/CaptionButtonStyle"
+ android:id="@+id/maximize_window"
+ android:layout_gravity="center_vertical|end"
+ android:contentDescription="@string/maximize_button_text"
+ android:background="@drawable/decor_maximize_button_dark"
+ android:duplicateParentState="true"/>
+ <Button
+ style="@style/CaptionButtonStyle"
+ android:id="@+id/close_window"
+ android:contentDescription="@string/close_button_text"
+ android:background="@drawable/decor_close_button_dark"
+ android:duplicateParentState="true"/>
+</com.android.wm.shell.windowdecor.WindowDecorLinearLayout>
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java
index af31391..6230d22 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java
@@ -17,6 +17,7 @@
import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE;
+import static com.android.wm.shell.bubbles.Bubble.KEY_APP_BUBBLE;
import static com.android.wm.shell.bubbles.BubbleDebugConfig.DEBUG_BUBBLE_DATA;
import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_BUBBLES;
import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME;
@@ -684,7 +685,8 @@
if (bubble.getPendingIntentCanceled()
|| !(reason == Bubbles.DISMISS_AGED
|| reason == Bubbles.DISMISS_USER_GESTURE
- || reason == Bubbles.DISMISS_RELOAD_FROM_DISK)) {
+ || reason == Bubbles.DISMISS_RELOAD_FROM_DISK)
+ || KEY_APP_BUBBLE.equals(bubble.getKey())) {
return;
}
if (DEBUG_BUBBLE_DATA) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
index 8121b20..e85b3c7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
@@ -232,10 +232,13 @@
if (mBubble.isAppBubble()) {
PendingIntent pi = PendingIntent.getActivity(mContext, 0,
- mBubble.getAppBubbleIntent(),
- PendingIntent.FLAG_MUTABLE,
+ mBubble.getAppBubbleIntent()
+ .addFlags(FLAG_ACTIVITY_NEW_DOCUMENT)
+ .addFlags(FLAG_ACTIVITY_MULTIPLE_TASK),
+ PendingIntent.FLAG_IMMUTABLE,
null);
- mTaskView.startActivity(pi, fillInIntent, options, launchBounds);
+ mTaskView.startActivity(pi, /* fillInIntent= */ null, options,
+ launchBounds);
} else if (!mIsOverflow && mBubble.hasMetadataShortcutId()) {
options.setApplyActivityFlagsForBubbles(true);
mTaskView.startShortcutActivity(mBubble.getShortcutInfo(),
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
index d0aef20..9edfffc 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
@@ -384,7 +384,7 @@
@Nullable ImeTracker.Token statsToken) {
final InsetsSource imeSource = mInsetsState.getSource(InsetsState.ITYPE_IME);
if (imeSource == null || mImeSourceControl == null) {
- ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_WM_ANIMATION_CREATE);
+ ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_WM_ANIMATION_CREATE);
return;
}
final Rect newFrame = imeSource.getFrame();
@@ -407,7 +407,8 @@
}
if ((!forceRestart && (mAnimationDirection == DIRECTION_SHOW && show))
|| (mAnimationDirection == DIRECTION_HIDE && !show)) {
- ImeTracker.get().onCancelled(statsToken, ImeTracker.PHASE_WM_ANIMATION_CREATE);
+ ImeTracker.forLogging().onCancelled(
+ statsToken, ImeTracker.PHASE_WM_ANIMATION_CREATE);
return;
}
boolean seek = false;
@@ -451,7 +452,7 @@
mTransactionPool.release(t);
});
mAnimation.setInterpolator(INTERPOLATOR);
- ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_WM_ANIMATION_CREATE);
+ ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_WM_ANIMATION_CREATE);
mAnimation.addListener(new AnimatorListenerAdapter() {
private boolean mCancelled = false;
@Nullable
@@ -474,7 +475,7 @@
: 1.f;
t.setAlpha(mImeSourceControl.getLeash(), alpha);
if (mAnimationDirection == DIRECTION_SHOW) {
- ImeTracker.get().onProgress(mStatsToken,
+ ImeTracker.forLogging().onProgress(mStatsToken,
ImeTracker.PHASE_WM_ANIMATION_RUNNING);
t.show(mImeSourceControl.getLeash());
}
@@ -511,15 +512,15 @@
}
dispatchEndPositioning(mDisplayId, mCancelled, t);
if (mAnimationDirection == DIRECTION_HIDE && !mCancelled) {
- ImeTracker.get().onProgress(mStatsToken,
+ ImeTracker.forLogging().onProgress(mStatsToken,
ImeTracker.PHASE_WM_ANIMATION_RUNNING);
t.hide(mImeSourceControl.getLeash());
removeImeSurface();
- ImeTracker.get().onHidden(mStatsToken);
+ ImeTracker.forLogging().onHidden(mStatsToken);
} else if (mAnimationDirection == DIRECTION_SHOW && !mCancelled) {
- ImeTracker.get().onShown(mStatsToken);
+ ImeTracker.forLogging().onShown(mStatsToken);
} else if (mCancelled) {
- ImeTracker.get().onCancelled(mStatsToken,
+ ImeTracker.forLogging().onCancelled(mStatsToken,
ImeTracker.PHASE_WM_ANIMATION_RUNNING);
}
if (DEBUG_IME_VISIBILITY) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayInsetsController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayInsetsController.java
index 8759301..9bdda14 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayInsetsController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayInsetsController.java
@@ -162,10 +162,12 @@
@Nullable ImeTracker.Token statsToken) {
CopyOnWriteArrayList<OnInsetsChangedListener> listeners = mListeners.get(mDisplayId);
if (listeners == null) {
- ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROLLER);
+ ImeTracker.forLogging().onFailed(
+ statsToken, ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROLLER);
return;
}
- ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROLLER);
+ ImeTracker.forLogging().onProgress(
+ statsToken, ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROLLER);
for (OnInsetsChangedListener listener : listeners) {
listener.showInsets(types, fromIme, statsToken);
}
@@ -175,10 +177,12 @@
@Nullable ImeTracker.Token statsToken) {
CopyOnWriteArrayList<OnInsetsChangedListener> listeners = mListeners.get(mDisplayId);
if (listeners == null) {
- ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROLLER);
+ ImeTracker.forLogging().onFailed(
+ statsToken, ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROLLER);
return;
}
- ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROLLER);
+ ImeTracker.forLogging().onProgress(
+ statsToken, ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROLLER);
for (OnInsetsChangedListener listener : listeners) {
listener.hideInsets(types, fromIme, statsToken);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
index fcbf9e0..fa3a6ad 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
@@ -78,6 +78,7 @@
private final Rect mResizingBounds = new Rect();
private final Rect mTempRect = new Rect();
private ValueAnimator mFadeAnimator;
+ private ValueAnimator mScreenshotAnimator;
private int mIconSize;
private int mOffsetX;
@@ -135,8 +136,17 @@
/** Releases the surfaces for split decor. */
public void release(SurfaceControl.Transaction t) {
- if (mFadeAnimator != null && mFadeAnimator.isRunning()) {
- mFadeAnimator.cancel();
+ if (mFadeAnimator != null) {
+ if (mFadeAnimator.isRunning()) {
+ mFadeAnimator.cancel();
+ }
+ mFadeAnimator = null;
+ }
+ if (mScreenshotAnimator != null) {
+ if (mScreenshotAnimator.isRunning()) {
+ mScreenshotAnimator.cancel();
+ }
+ mScreenshotAnimator = null;
}
if (mViewHost != null) {
mViewHost.release();
@@ -238,16 +248,20 @@
/** Stops showing resizing hint. */
public void onResized(SurfaceControl.Transaction t, Runnable animFinishedCallback) {
if (mScreenshot != null) {
+ if (mScreenshotAnimator != null && mScreenshotAnimator.isRunning()) {
+ mScreenshotAnimator.cancel();
+ }
+
t.setPosition(mScreenshot, mOffsetX, mOffsetY);
final SurfaceControl.Transaction animT = new SurfaceControl.Transaction();
- final ValueAnimator va = ValueAnimator.ofFloat(1, 0);
- va.addUpdateListener(valueAnimator -> {
+ mScreenshotAnimator = ValueAnimator.ofFloat(1, 0);
+ mScreenshotAnimator.addUpdateListener(valueAnimator -> {
final float progress = (float) valueAnimator.getAnimatedValue();
animT.setAlpha(mScreenshot, progress);
animT.apply();
});
- va.addListener(new AnimatorListenerAdapter() {
+ mScreenshotAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
mRunningAnimationCount++;
@@ -266,7 +280,7 @@
}
}
});
- va.start();
+ mScreenshotAnimator.start();
}
if (mResizingIconView == null) {
@@ -292,9 +306,6 @@
});
return;
}
-
- // If fade-in animation is running, cancel it and re-run fade-out one.
- mFadeAnimator.cancel();
}
if (mShown) {
fadeOutDecor(animFinishedCallback);
@@ -332,6 +343,11 @@
* directly. */
public void fadeOutDecor(Runnable finishedCallback) {
if (mShown) {
+ // If previous animation is running, just cancel it.
+ if (mFadeAnimator != null && mFadeAnimator.isRunning()) {
+ mFadeAnimator.cancel();
+ }
+
startFadeAnimation(false /* show */, true, finishedCallback);
mShown = false;
} else {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index d3b9fa5..512a4ef 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -49,6 +49,7 @@
import com.android.wm.shell.common.annotations.ShellBackgroundThread;
import com.android.wm.shell.common.annotations.ShellMainThread;
import com.android.wm.shell.desktopmode.DesktopModeController;
+import com.android.wm.shell.desktopmode.DesktopModeStatus;
import com.android.wm.shell.desktopmode.DesktopModeTaskRepository;
import com.android.wm.shell.desktopmode.DesktopTasksController;
import com.android.wm.shell.draganddrop.DragAndDropController;
@@ -93,6 +94,7 @@
import com.android.wm.shell.unfold.animation.UnfoldTaskAnimator;
import com.android.wm.shell.unfold.qualifier.UnfoldShellTransition;
import com.android.wm.shell.unfold.qualifier.UnfoldTransition;
+import com.android.wm.shell.windowdecor.CaptionWindowDecorViewModel;
import com.android.wm.shell.windowdecor.DesktopModeWindowDecorViewModel;
import com.android.wm.shell.windowdecor.WindowDecorViewModel;
@@ -192,7 +194,8 @@
SyncTransactionQueue syncQueue,
Optional<DesktopModeController> desktopModeController,
Optional<DesktopTasksController> desktopTasksController) {
- return new DesktopModeWindowDecorViewModel(
+ if (DesktopModeStatus.isAnyEnabled()) {
+ return new DesktopModeWindowDecorViewModel(
context,
mainHandler,
mainChoreographer,
@@ -201,6 +204,14 @@
syncQueue,
desktopModeController,
desktopTasksController);
+ }
+ return new CaptionWindowDecorViewModel(
+ context,
+ mainHandler,
+ mainChoreographer,
+ taskOrganizer,
+ displayController,
+ syncQueue);
}
//
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java
index cd61dbb..f6d67d8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java
@@ -47,7 +47,7 @@
private final @NonNull PipBoundsState mPipBoundsState;
private final PipSnapAlgorithm mSnapAlgorithm;
- private final PipKeepClearAlgorithm mPipKeepClearAlgorithm;
+ private final PipKeepClearAlgorithmInterface mPipKeepClearAlgorithm;
private float mDefaultSizePercent;
private float mMinAspectRatioForMinSize;
@@ -62,7 +62,7 @@
public PipBoundsAlgorithm(Context context, @NonNull PipBoundsState pipBoundsState,
@NonNull PipSnapAlgorithm pipSnapAlgorithm,
- @NonNull PipKeepClearAlgorithm pipKeepClearAlgorithm) {
+ @NonNull PipKeepClearAlgorithmInterface pipKeepClearAlgorithm) {
mPipBoundsState = pipBoundsState;
mSnapAlgorithm = pipSnapAlgorithm;
mPipKeepClearAlgorithm = pipKeepClearAlgorithm;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipKeepClearAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipKeepClearAlgorithmInterface.java
similarity index 97%
rename from libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipKeepClearAlgorithm.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipKeepClearAlgorithmInterface.java
index e3495e1..5045cf9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipKeepClearAlgorithm.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipKeepClearAlgorithmInterface.java
@@ -24,7 +24,7 @@
* Interface for interacting with keep clear algorithm used to move PiP window out of the way of
* keep clear areas.
*/
-public interface PipKeepClearAlgorithm {
+public interface PipKeepClearAlgorithmInterface {
/**
* Adjust the position of picture in picture window based on the registered keep clear areas.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithm.java
index 690505e..ed8dc7de 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithm.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithm.java
@@ -26,14 +26,14 @@
import com.android.wm.shell.R;
import com.android.wm.shell.pip.PipBoundsAlgorithm;
import com.android.wm.shell.pip.PipBoundsState;
-import com.android.wm.shell.pip.PipKeepClearAlgorithm;
+import com.android.wm.shell.pip.PipKeepClearAlgorithmInterface;
import java.util.Set;
/**
* Calculates the adjusted position that does not occlude keep clear areas.
*/
-public class PhonePipKeepClearAlgorithm implements PipKeepClearAlgorithm {
+public class PhonePipKeepClearAlgorithm implements PipKeepClearAlgorithmInterface {
private boolean mKeepClearAreaGravityEnabled =
SystemProperties.getBoolean(
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
index 3153313..e83854e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
@@ -46,8 +46,6 @@
import android.graphics.Rect;
import android.os.RemoteException;
import android.os.SystemProperties;
-import android.os.UserHandle;
-import android.os.UserManager;
import android.util.Pair;
import android.util.Size;
import android.view.DisplayInfo;
@@ -85,7 +83,7 @@
import com.android.wm.shell.pip.PipAppOpsListener;
import com.android.wm.shell.pip.PipBoundsAlgorithm;
import com.android.wm.shell.pip.PipBoundsState;
-import com.android.wm.shell.pip.PipKeepClearAlgorithm;
+import com.android.wm.shell.pip.PipKeepClearAlgorithmInterface;
import com.android.wm.shell.pip.PipMediaController;
import com.android.wm.shell.pip.PipParamsChangedForwarder;
import com.android.wm.shell.pip.PipSnapAlgorithm;
@@ -137,7 +135,7 @@
private PipAppOpsListener mAppOpsListener;
private PipMediaController mMediaController;
private PipBoundsAlgorithm mPipBoundsAlgorithm;
- private PipKeepClearAlgorithm mPipKeepClearAlgorithm;
+ private PipKeepClearAlgorithmInterface mPipKeepClearAlgorithm;
private PipBoundsState mPipBoundsState;
private PipMotionHelper mPipMotionHelper;
private PipTouchHandler mTouchHandler;
@@ -380,7 +378,7 @@
PipAnimationController pipAnimationController,
PipAppOpsListener pipAppOpsListener,
PipBoundsAlgorithm pipBoundsAlgorithm,
- PipKeepClearAlgorithm pipKeepClearAlgorithm,
+ PipKeepClearAlgorithmInterface pipKeepClearAlgorithm,
PipBoundsState pipBoundsState,
PipMotionHelper pipMotionHelper,
PipMediaController pipMediaController,
@@ -419,7 +417,7 @@
PipAnimationController pipAnimationController,
PipAppOpsListener pipAppOpsListener,
PipBoundsAlgorithm pipBoundsAlgorithm,
- PipKeepClearAlgorithm pipKeepClearAlgorithm,
+ PipKeepClearAlgorithmInterface pipKeepClearAlgorithm,
@NonNull PipBoundsState pipBoundsState,
PipMotionHelper pipMotionHelper,
PipMediaController pipMediaController,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsAlgorithm.java
index 31490e4..b042063 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsAlgorithm.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsAlgorithm.java
@@ -37,7 +37,7 @@
import com.android.wm.shell.R;
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.pip.PipBoundsAlgorithm;
-import com.android.wm.shell.pip.PipKeepClearAlgorithm;
+import com.android.wm.shell.pip.PipKeepClearAlgorithmInterface;
import com.android.wm.shell.pip.PipSnapAlgorithm;
import com.android.wm.shell.pip.tv.TvPipKeepClearAlgorithm.Placement;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
@@ -62,7 +62,7 @@
@NonNull TvPipBoundsState tvPipBoundsState,
@NonNull PipSnapAlgorithm pipSnapAlgorithm) {
super(context, tvPipBoundsState, pipSnapAlgorithm,
- new PipKeepClearAlgorithm() {
+ new PipKeepClearAlgorithmInterface() {
});
this.mTvPipBoundsState = tvPipBoundsState;
this.mKeepClearAlgorithm = new TvPipKeepClearAlgorithm();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsController.java
index b189163..8d4a384 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsController.java
@@ -125,7 +125,9 @@
cancelScheduledPlacement();
applyPlacement(placement, shouldStash, animationDuration);
} else {
- applyPlacementBounds(mCurrentPlacementBounds, animationDuration);
+ if (mCurrentPlacementBounds != null) {
+ applyPlacementBounds(mCurrentPlacementBounds, animationDuration);
+ }
schedulePinnedStackPlacement(placement, animationDuration);
}
}
@@ -188,7 +190,7 @@
applyPlacementBounds(bounds, animationDuration);
}
- void onPipDismissed() {
+ void reset() {
mCurrentPlacementBounds = null;
mPipTargetBounds = null;
cancelScheduledPlacement();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java
index fd4fcff..4426423 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java
@@ -450,18 +450,6 @@
mPipMediaController.registerSessionListenerForCurrentUser();
}
- private void checkIfPinnedTaskAppeared() {
- final TaskInfo pinnedTask = getPinnedTaskInfo();
- ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
- "%s: checkIfPinnedTaskAppeared(), task=%s", TAG, pinnedTask);
- if (pinnedTask == null || pinnedTask.topActivity == null) return;
- mPinnedTaskId = pinnedTask.taskId;
-
- mPipMediaController.onActivityPinned();
- mActionBroadcastReceiver.register();
- mPipNotificationController.show(pinnedTask.topActivity.getPackageName());
- }
-
private void checkIfPinnedTaskIsGone() {
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: onTaskStackChanged()", TAG);
@@ -482,7 +470,7 @@
mTvPipMenuController.closeMenu();
mTvPipBoundsState.resetTvPipState();
- mTvPipBoundsController.onPipDismissed();
+ mTvPipBoundsController.reset();
setState(STATE_NO_PIP);
mPinnedTaskId = NONEXISTENT_TASK_ID;
}
@@ -537,7 +525,16 @@
taskStackListener.addListener(new TaskStackListenerCallback() {
@Override
public void onActivityPinned(String packageName, int userId, int taskId, int stackId) {
- checkIfPinnedTaskAppeared();
+ final TaskInfo pinnedTask = getPinnedTaskInfo();
+ ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+ "%s: onActivityPinned(), task=%s", TAG, pinnedTask);
+ if (pinnedTask == null || pinnedTask.topActivity == null) return;
+ mPinnedTaskId = pinnedTask.taskId;
+
+ mPipMediaController.onActivityPinned();
+ mActionBroadcastReceiver.register();
+ mPipNotificationController.show(pinnedTask.topActivity.getPackageName());
+ mTvPipBoundsController.reset();
mAppOpsListener.onActivityPinned(packageName);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 8ddc3c04..a6c4ac2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -605,9 +605,19 @@
float splitRatio, RemoteAnimationAdapter adapter, InstanceId instanceId) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
if (options1 == null) options1 = new Bundle();
+ if (taskId2 == INVALID_TASK_ID) {
+ // Launching a solo task.
+ ActivityOptions activityOptions = ActivityOptions.fromBundle(options1);
+ activityOptions.update(ActivityOptions.makeRemoteAnimation(adapter));
+ options1 = activityOptions.toBundle();
+ addActivityOptions(options1, null /* launchTarget */);
+ wct.startTask(taskId1, options1);
+ mSyncQueue.queue(wct);
+ return;
+ }
+
addActivityOptions(options1, mSideStage);
wct.startTask(taskId1, options1);
-
startWithLegacyTransition(wct, taskId2, options2, splitPosition, splitRatio, adapter,
instanceId);
}
@@ -632,9 +642,19 @@
InstanceId instanceId) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
if (options1 == null) options1 = new Bundle();
+ if (taskId == INVALID_TASK_ID) {
+ // Launching a solo task.
+ ActivityOptions activityOptions = ActivityOptions.fromBundle(options1);
+ activityOptions.update(ActivityOptions.makeRemoteAnimation(adapter));
+ options1 = activityOptions.toBundle();
+ addActivityOptions(options1, null /* launchTarget */);
+ wct.sendPendingIntent(pendingIntent, fillInIntent, options1);
+ mSyncQueue.queue(wct);
+ return;
+ }
+
addActivityOptions(options1, mSideStage);
wct.sendPendingIntent(pendingIntent, fillInIntent, options1);
-
startWithLegacyTransition(wct, taskId, options2, splitPosition, splitRatio, adapter,
instanceId);
}
@@ -696,6 +716,34 @@
mShouldUpdateRecents = false;
mIsSplitEntering = true;
+ setSideStagePosition(sidePosition, wct);
+ if (!mMainStage.isActive()) {
+ mMainStage.activate(wct, false /* reparent */);
+ }
+
+ if (mainOptions == null) mainOptions = new Bundle();
+ addActivityOptions(mainOptions, mMainStage);
+ mainOptions = wrapAsSplitRemoteAnimation(adapter, mainOptions);
+
+ updateWindowBounds(mSplitLayout, wct);
+ if (mainTaskId == INVALID_TASK_ID) {
+ wct.sendPendingIntent(mainPendingIntent, mainFillInIntent, mainOptions);
+ } else {
+ wct.startTask(mainTaskId, mainOptions);
+ }
+
+ wct.reorder(mRootTaskInfo.token, true);
+ wct.setForceTranslucent(mRootTaskInfo.token, false);
+
+ mSyncQueue.queue(wct);
+ mSyncQueue.runInSync(t -> {
+ setDividerVisibility(true, t);
+ });
+
+ setEnterInstanceId(instanceId);
+ }
+
+ private Bundle wrapAsSplitRemoteAnimation(RemoteAnimationAdapter adapter, Bundle options) {
final WindowContainerTransaction evictWct = new WindowContainerTransaction();
if (isSplitScreenVisible()) {
mMainStage.evictAllChildren(evictWct);
@@ -739,37 +787,9 @@
};
RemoteAnimationAdapter wrappedAdapter = new RemoteAnimationAdapter(
wrapper, adapter.getDuration(), adapter.getStatusBarTransitionDelay());
-
- if (mainOptions == null) {
- mainOptions = ActivityOptions.makeRemoteAnimation(wrappedAdapter).toBundle();
- } else {
- ActivityOptions mainActivityOptions = ActivityOptions.fromBundle(mainOptions);
- mainActivityOptions.update(ActivityOptions.makeRemoteAnimation(wrappedAdapter));
- mainOptions = mainActivityOptions.toBundle();
- }
-
- setSideStagePosition(sidePosition, wct);
- if (!mMainStage.isActive()) {
- mMainStage.activate(wct, false /* reparent */);
- }
-
- if (mainOptions == null) mainOptions = new Bundle();
- addActivityOptions(mainOptions, mMainStage);
- updateWindowBounds(mSplitLayout, wct);
- if (mainTaskId == INVALID_TASK_ID) {
- wct.sendPendingIntent(mainPendingIntent, mainFillInIntent, mainOptions);
- } else {
- wct.startTask(mainTaskId, mainOptions);
- }
- wct.reorder(mRootTaskInfo.token, true);
- wct.setForceTranslucent(mRootTaskInfo.token, false);
-
- mSyncQueue.queue(wct);
- mSyncQueue.runInSync(t -> {
- setDividerVisibility(true, t);
- });
-
- setEnterInstanceId(instanceId);
+ ActivityOptions activityOptions = ActivityOptions.fromBundle(options);
+ activityOptions.update(ActivityOptions.makeRemoteAnimation(wrappedAdapter));
+ return activityOptions.toBundle();
}
private void setEnterInstanceId(InstanceId instanceId) {
@@ -1052,6 +1072,7 @@
mSideStage.removeAllTasks(wct, false /* toTop */);
mMainStage.deactivate(wct, false /* toTop */);
wct.reorder(mRootTaskInfo.token, false /* onTop */);
+ wct.setForceTranslucent(mRootTaskInfo.token, true);
wct.setBounds(mSideStage.mRootTaskInfo.token, mTempRect1);
onTransitionAnimationComplete();
} else {
@@ -1083,6 +1104,7 @@
mMainStage.deactivate(finishedWCT, childrenToTop == mMainStage /* toTop */);
mSideStage.removeAllTasks(finishedWCT, childrenToTop == mSideStage /* toTop */);
finishedWCT.reorder(mRootTaskInfo.token, false /* toTop */);
+ finishedWCT.setForceTranslucent(mRootTaskInfo.token, true);
finishedWCT.setBounds(mSideStage.mRootTaskInfo.token, mTempRect1);
mSyncQueue.queue(finishedWCT);
mSyncQueue.runInSync(at -> {
@@ -1228,8 +1250,10 @@
return SPLIT_POSITION_UNDEFINED;
}
- private void addActivityOptions(Bundle opts, StageTaskListener stage) {
- opts.putParcelable(KEY_LAUNCH_ROOT_TASK_TOKEN, stage.mRootTaskInfo.token);
+ private void addActivityOptions(Bundle opts, @Nullable StageTaskListener launchTarget) {
+ if (launchTarget != null) {
+ opts.putParcelable(KEY_LAUNCH_ROOT_TASK_TOKEN, launchTarget.mRootTaskInfo.token);
+ }
// Put BAL flags to avoid activity start aborted. Otherwise, flows like shortcut to split
// will be canceled.
opts.putBoolean(KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED, true);
@@ -1463,6 +1487,12 @@
}
private void onStageVisibilityChanged(StageListenerImpl stageListener) {
+ // If split didn't active, just ignore this callback because we should already did these
+ // on #applyExitSplitScreen.
+ if (!isSplitActive()) {
+ return;
+ }
+
final boolean sideStageVisible = mSideStageListener.mVisible;
final boolean mainStageVisible = mMainStageListener.mVisible;
@@ -1471,20 +1501,23 @@
return;
}
+ // Check if it needs to dismiss split screen when both stage invisible.
+ if (!mainStageVisible && mExitSplitScreenOnHide) {
+ exitSplitScreen(null /* childrenToTop */, EXIT_REASON_RETURN_HOME);
+ return;
+ }
+
final WindowContainerTransaction wct = new WindowContainerTransaction();
if (!mainStageVisible) {
+ // Split entering background.
wct.setReparentLeafTaskIfRelaunch(mRootTaskInfo.token,
true /* setReparentLeafTaskIfRelaunch */);
wct.setForceTranslucent(mRootTaskInfo.token, true);
- // Both stages are not visible, check if it needs to dismiss split screen.
- if (mExitSplitScreenOnHide) {
- exitSplitScreen(null /* childrenToTop */, EXIT_REASON_RETURN_HOME);
- }
} else {
wct.setReparentLeafTaskIfRelaunch(mRootTaskInfo.token,
false /* setReparentLeafTaskIfRelaunch */);
- wct.setForceTranslucent(mRootTaskInfo.token, false);
}
+
mSyncQueue.queue(wct);
mSyncQueue.runInSync(t -> {
setDividerVisibility(mainStageVisible, t);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java
index 66d0a2a..665267f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java
@@ -170,6 +170,7 @@
if (!isCustomRotate()) {
mStartLuma = TransitionAnimation.getBorderLuma(hardwareBuffer, colorSpace);
}
+ hardwareBuffer.close();
}
t.setLayer(mAnimLeash, SCREEN_FREEZE_LAYER_BASE);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
new file mode 100644
index 0000000..129924a
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.windowdecor;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+
+import android.app.ActivityManager.RunningTaskInfo;
+import android.content.Context;
+import android.os.Handler;
+import android.util.SparseArray;
+import android.view.Choreographer;
+import android.view.MotionEvent;
+import android.view.SurfaceControl;
+import android.view.View;
+import android.window.WindowContainerToken;
+import android.window.WindowContainerTransaction;
+
+import com.android.wm.shell.R;
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.SyncTransactionQueue;
+import com.android.wm.shell.freeform.FreeformTaskTransitionStarter;
+
+/**
+ * View model for the window decoration with a caption and shadows. Works with
+ * {@link CaptionWindowDecoration}.
+ */
+public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
+ private final ShellTaskOrganizer mTaskOrganizer;
+ private final Context mContext;
+ private final Handler mMainHandler;
+ private final Choreographer mMainChoreographer;
+ private final DisplayController mDisplayController;
+ private final SyncTransactionQueue mSyncQueue;
+ private TaskOperations mTaskOperations;
+
+ private final SparseArray<CaptionWindowDecoration> mWindowDecorByTaskId = new SparseArray<>();
+
+ public CaptionWindowDecorViewModel(
+ Context context,
+ Handler mainHandler,
+ Choreographer mainChoreographer,
+ ShellTaskOrganizer taskOrganizer,
+ DisplayController displayController,
+ SyncTransactionQueue syncQueue) {
+ mContext = context;
+ mMainHandler = mainHandler;
+ mMainChoreographer = mainChoreographer;
+ mTaskOrganizer = taskOrganizer;
+ mDisplayController = displayController;
+ mSyncQueue = syncQueue;
+ }
+
+ @Override
+ public void setFreeformTaskTransitionStarter(FreeformTaskTransitionStarter transitionStarter) {
+ mTaskOperations = new TaskOperations(transitionStarter, mContext, mSyncQueue);
+ }
+
+ @Override
+ public boolean onTaskOpening(
+ RunningTaskInfo taskInfo,
+ SurfaceControl taskSurface,
+ SurfaceControl.Transaction startT,
+ SurfaceControl.Transaction finishT) {
+ if (!shouldShowWindowDecor(taskInfo)) return false;
+ createWindowDecoration(taskInfo, taskSurface, startT, finishT);
+ return true;
+ }
+
+ @Override
+ public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
+ final CaptionWindowDecoration decoration = mWindowDecorByTaskId.get(taskInfo.taskId);
+
+ if (decoration == null) return;
+
+ decoration.relayout(taskInfo);
+ setupCaptionColor(taskInfo, decoration);
+ }
+
+ @Override
+ public void onTaskChanging(
+ RunningTaskInfo taskInfo,
+ SurfaceControl taskSurface,
+ SurfaceControl.Transaction startT,
+ SurfaceControl.Transaction finishT) {
+ final CaptionWindowDecoration decoration = mWindowDecorByTaskId.get(taskInfo.taskId);
+
+ if (!shouldShowWindowDecor(taskInfo)) {
+ if (decoration != null) {
+ destroyWindowDecoration(taskInfo);
+ }
+ return;
+ }
+
+ if (decoration == null) {
+ createWindowDecoration(taskInfo, taskSurface, startT, finishT);
+ } else {
+ decoration.relayout(taskInfo, startT, finishT);
+ }
+ }
+
+ @Override
+ public void onTaskClosing(
+ RunningTaskInfo taskInfo,
+ SurfaceControl.Transaction startT,
+ SurfaceControl.Transaction finishT) {
+ final CaptionWindowDecoration decoration = mWindowDecorByTaskId.get(taskInfo.taskId);
+ if (decoration == null) return;
+
+ decoration.relayout(taskInfo, startT, finishT);
+ }
+
+ @Override
+ public void destroyWindowDecoration(RunningTaskInfo taskInfo) {
+ final CaptionWindowDecoration decoration =
+ mWindowDecorByTaskId.removeReturnOld(taskInfo.taskId);
+ if (decoration == null) return;
+
+ decoration.close();
+ }
+
+ private void setupCaptionColor(RunningTaskInfo taskInfo, CaptionWindowDecoration decoration) {
+ final int statusBarColor = taskInfo.taskDescription.getStatusBarColor();
+ decoration.setCaptionColor(statusBarColor);
+ }
+
+ private boolean shouldShowWindowDecor(RunningTaskInfo taskInfo) {
+ return taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM
+ || (taskInfo.getActivityType() == ACTIVITY_TYPE_STANDARD
+ && taskInfo.configuration.windowConfiguration.getDisplayWindowingMode()
+ == WINDOWING_MODE_FREEFORM);
+ }
+
+ private void createWindowDecoration(
+ RunningTaskInfo taskInfo,
+ SurfaceControl taskSurface,
+ SurfaceControl.Transaction startT,
+ SurfaceControl.Transaction finishT) {
+ final CaptionWindowDecoration oldDecoration = mWindowDecorByTaskId.get(taskInfo.taskId);
+ if (oldDecoration != null) {
+ // close the old decoration if it exists to avoid two window decorations being added
+ oldDecoration.close();
+ }
+ final CaptionWindowDecoration windowDecoration =
+ new CaptionWindowDecoration(
+ mContext,
+ mDisplayController,
+ mTaskOrganizer,
+ taskInfo,
+ taskSurface,
+ mMainHandler,
+ mMainChoreographer,
+ mSyncQueue);
+ mWindowDecorByTaskId.put(taskInfo.taskId, windowDecoration);
+
+ final TaskPositioner taskPositioner =
+ new TaskPositioner(mTaskOrganizer, windowDecoration);
+ final CaptionTouchEventListener touchEventListener =
+ new CaptionTouchEventListener(taskInfo, taskPositioner);
+ windowDecoration.setCaptionListeners(touchEventListener, touchEventListener);
+ windowDecoration.setDragResizeCallback(taskPositioner);
+ windowDecoration.relayout(taskInfo, startT, finishT);
+ setupCaptionColor(taskInfo, windowDecoration);
+ }
+
+ private class CaptionTouchEventListener implements
+ View.OnClickListener, View.OnTouchListener {
+
+ private final int mTaskId;
+ private final WindowContainerToken mTaskToken;
+ private final DragResizeCallback mDragResizeCallback;
+
+ private int mDragPointerId = -1;
+
+ private CaptionTouchEventListener(
+ RunningTaskInfo taskInfo,
+ DragResizeCallback dragResizeCallback) {
+ mTaskId = taskInfo.taskId;
+ mTaskToken = taskInfo.token;
+ mDragResizeCallback = dragResizeCallback;
+ }
+
+ @Override
+ public void onClick(View v) {
+ final int id = v.getId();
+ if (id == R.id.close_window) {
+ mTaskOperations.closeTask(mTaskToken);
+ } else if (id == R.id.back_button) {
+ mTaskOperations.injectBackKey();
+ } else if (id == R.id.minimize_window) {
+ mTaskOperations.minimizeTask(mTaskToken);
+ } else if (id == R.id.maximize_window) {
+ RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId);
+ mTaskOperations.maximizeTask(taskInfo);
+ }
+ }
+
+ @Override
+ public boolean onTouch(View v, MotionEvent e) {
+ if (v.getId() != R.id.caption) {
+ return false;
+ }
+ handleEventForMove(e);
+
+ if (e.getAction() != MotionEvent.ACTION_DOWN) {
+ return false;
+ }
+ final RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId);
+ if (taskInfo.isFocused) {
+ return false;
+ }
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+ wct.reorder(mTaskToken, true /* onTop */);
+ mSyncQueue.queue(wct);
+ return true;
+ }
+
+ /**
+ * @param e {@link MotionEvent} to process
+ * @return {@code true} if a drag is happening; or {@code false} if it is not
+ */
+ private void handleEventForMove(MotionEvent e) {
+ final RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId);
+ if (taskInfo.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
+ return;
+ }
+ switch (e.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN: {
+ mDragPointerId = e.getPointerId(0);
+ mDragResizeCallback.onDragResizeStart(
+ 0 /* ctrlType */, e.getRawX(0), e.getRawY(0));
+ break;
+ }
+ case MotionEvent.ACTION_MOVE: {
+ int dragPointerIdx = e.findPointerIndex(mDragPointerId);
+ mDragResizeCallback.onDragResizeMove(
+ e.getRawX(dragPointerIdx), e.getRawY(dragPointerIdx));
+ break;
+ }
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL: {
+ int dragPointerIdx = e.findPointerIndex(mDragPointerId);
+ mDragResizeCallback.onDragResizeEnd(
+ e.getRawX(dragPointerIdx), e.getRawY(dragPointerIdx));
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
new file mode 100644
index 0000000..d26f1fc
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.windowdecor;
+
+import android.app.ActivityManager.RunningTaskInfo;
+import android.app.WindowConfiguration;
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.Color;
+import android.graphics.drawable.GradientDrawable;
+import android.graphics.drawable.VectorDrawable;
+import android.os.Handler;
+import android.view.Choreographer;
+import android.view.SurfaceControl;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.window.WindowContainerTransaction;
+
+import com.android.wm.shell.R;
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.SyncTransactionQueue;
+
+/**
+ * Defines visuals and behaviors of a window decoration of a caption bar and shadows. It works with
+ * {@link CaptionWindowDecorViewModel}. The caption bar contains a back button, minimize button,
+ * maximize button and close button.
+ */
+public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearLayout> {
+ private final Handler mHandler;
+ private final Choreographer mChoreographer;
+ private final SyncTransactionQueue mSyncQueue;
+
+ private View.OnClickListener mOnCaptionButtonClickListener;
+ private View.OnTouchListener mOnCaptionTouchListener;
+ private DragResizeCallback mDragResizeCallback;
+ private DragResizeInputListener mDragResizeListener;
+ private final DragDetector mDragDetector;
+
+ private RelayoutParams mRelayoutParams = new RelayoutParams();
+ private final RelayoutResult<WindowDecorLinearLayout> mResult =
+ new RelayoutResult<>();
+
+ CaptionWindowDecoration(
+ Context context,
+ DisplayController displayController,
+ ShellTaskOrganizer taskOrganizer,
+ RunningTaskInfo taskInfo,
+ SurfaceControl taskSurface,
+ Handler handler,
+ Choreographer choreographer,
+ SyncTransactionQueue syncQueue) {
+ super(context, displayController, taskOrganizer, taskInfo, taskSurface);
+
+ mHandler = handler;
+ mChoreographer = choreographer;
+ mSyncQueue = syncQueue;
+ mDragDetector = new DragDetector(ViewConfiguration.get(context).getScaledTouchSlop());
+ }
+
+ void setCaptionListeners(
+ View.OnClickListener onCaptionButtonClickListener,
+ View.OnTouchListener onCaptionTouchListener) {
+ mOnCaptionButtonClickListener = onCaptionButtonClickListener;
+ mOnCaptionTouchListener = onCaptionTouchListener;
+ }
+
+ void setDragResizeCallback(DragResizeCallback dragResizeCallback) {
+ mDragResizeCallback = dragResizeCallback;
+ }
+
+ @Override
+ void relayout(RunningTaskInfo taskInfo) {
+ final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ relayout(taskInfo, t, t);
+ mSyncQueue.runInSync(transaction -> {
+ transaction.merge(t);
+ t.close();
+ });
+ }
+
+ void relayout(RunningTaskInfo taskInfo,
+ SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT) {
+ final int shadowRadiusID = taskInfo.isFocused
+ ? R.dimen.freeform_decor_shadow_focused_thickness
+ : R.dimen.freeform_decor_shadow_unfocused_thickness;
+ final boolean isFreeform =
+ taskInfo.getWindowingMode() == WindowConfiguration.WINDOWING_MODE_FREEFORM;
+ final boolean isDragResizeable = isFreeform && taskInfo.isResizeable;
+
+ final WindowDecorLinearLayout oldRootView = mResult.mRootView;
+ final SurfaceControl oldDecorationSurface = mDecorationContainerSurface;
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+
+ final int outsetLeftId = R.dimen.freeform_resize_handle;
+ final int outsetTopId = R.dimen.freeform_resize_handle;
+ final int outsetRightId = R.dimen.freeform_resize_handle;
+ final int outsetBottomId = R.dimen.freeform_resize_handle;
+
+ mRelayoutParams.reset();
+ mRelayoutParams.mRunningTaskInfo = taskInfo;
+ mRelayoutParams.mLayoutResId = R.layout.caption_window_decor;
+ mRelayoutParams.mCaptionHeightId = R.dimen.freeform_decor_caption_height;
+ mRelayoutParams.mShadowRadiusId = shadowRadiusID;
+ if (isDragResizeable) {
+ mRelayoutParams.setOutsets(outsetLeftId, outsetTopId, outsetRightId, outsetBottomId);
+ }
+
+ relayout(mRelayoutParams, startT, finishT, wct, oldRootView, mResult);
+ // After this line, mTaskInfo is up-to-date and should be used instead of taskInfo
+
+ mTaskOrganizer.applyTransaction(wct);
+
+ if (mResult.mRootView == null) {
+ // This means something blocks the window decor from showing, e.g. the task is hidden.
+ // Nothing is set up in this case including the decoration surface.
+ return;
+ }
+ if (oldRootView != mResult.mRootView) {
+ setupRootView();
+ }
+
+ if (!isDragResizeable) {
+ closeDragResizeListener();
+ return;
+ }
+
+ if (oldDecorationSurface != mDecorationContainerSurface || mDragResizeListener == null) {
+ closeDragResizeListener();
+ mDragResizeListener = new DragResizeInputListener(
+ mContext,
+ mHandler,
+ mChoreographer,
+ mDisplay.getDisplayId(),
+ mDecorationContainerSurface,
+ mDragResizeCallback);
+ }
+
+ final int touchSlop = ViewConfiguration.get(mResult.mRootView.getContext())
+ .getScaledTouchSlop();
+ mDragDetector.setTouchSlop(touchSlop);
+
+ final int resize_handle = mResult.mRootView.getResources()
+ .getDimensionPixelSize(R.dimen.freeform_resize_handle);
+ final int resize_corner = mResult.mRootView.getResources()
+ .getDimensionPixelSize(R.dimen.freeform_resize_corner);
+ mDragResizeListener.setGeometry(
+ mResult.mWidth, mResult.mHeight, resize_handle, resize_corner, touchSlop);
+ }
+
+ /**
+ * Sets up listeners when a new root view is created.
+ */
+ private void setupRootView() {
+ final View caption = mResult.mRootView.findViewById(R.id.caption);
+ caption.setOnTouchListener(mOnCaptionTouchListener);
+ final View close = caption.findViewById(R.id.close_window);
+ close.setOnClickListener(mOnCaptionButtonClickListener);
+ final View back = caption.findViewById(R.id.back_button);
+ back.setOnClickListener(mOnCaptionButtonClickListener);
+ final View minimize = caption.findViewById(R.id.minimize_window);
+ minimize.setOnClickListener(mOnCaptionButtonClickListener);
+ final View maximize = caption.findViewById(R.id.maximize_window);
+ maximize.setOnClickListener(mOnCaptionButtonClickListener);
+ }
+
+ void setCaptionColor(int captionColor) {
+ if (mResult.mRootView == null) {
+ return;
+ }
+
+ final View caption = mResult.mRootView.findViewById(R.id.caption);
+ final GradientDrawable captionDrawable = (GradientDrawable) caption.getBackground();
+ captionDrawable.setColor(captionColor);
+
+ final int buttonTintColorRes =
+ Color.valueOf(captionColor).luminance() < 0.5
+ ? R.color.decor_button_light_color
+ : R.color.decor_button_dark_color;
+ final ColorStateList buttonTintColor =
+ caption.getResources().getColorStateList(buttonTintColorRes, null /* theme */);
+
+ final View back = caption.findViewById(R.id.back_button);
+ final VectorDrawable backBackground = (VectorDrawable) back.getBackground();
+ backBackground.setTintList(buttonTintColor);
+
+ final View minimize = caption.findViewById(R.id.minimize_window);
+ final VectorDrawable minimizeBackground = (VectorDrawable) minimize.getBackground();
+ minimizeBackground.setTintList(buttonTintColor);
+
+ final View maximize = caption.findViewById(R.id.maximize_window);
+ final VectorDrawable maximizeBackground = (VectorDrawable) maximize.getBackground();
+ maximizeBackground.setTintList(buttonTintColor);
+
+ final View close = caption.findViewById(R.id.close_window);
+ final VectorDrawable closeBackground = (VectorDrawable) close.getBackground();
+ closeBackground.setTintList(buttonTintColor);
+ }
+
+ private void closeDragResizeListener() {
+ if (mDragResizeListener == null) {
+ return;
+ }
+ mDragResizeListener.close();
+ mDragResizeListener = null;
+ }
+
+ @Override
+ public void close() {
+ closeDragResizeListener();
+ super.close();
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
index 00aab67..2863adc 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
@@ -27,17 +27,12 @@
import android.hardware.input.InputManager;
import android.os.Handler;
import android.os.Looper;
-import android.os.SystemClock;
-import android.util.Log;
import android.util.SparseArray;
import android.view.Choreographer;
import android.view.InputChannel;
-import android.view.InputDevice;
import android.view.InputEvent;
import android.view.InputEventReceiver;
import android.view.InputMonitor;
-import android.view.KeyCharacterMap;
-import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceControl;
import android.view.View;
@@ -55,7 +50,6 @@
import com.android.wm.shell.desktopmode.DesktopModeStatus;
import com.android.wm.shell.desktopmode.DesktopTasksController;
import com.android.wm.shell.freeform.FreeformTaskTransitionStarter;
-import com.android.wm.shell.transition.Transitions;
import java.util.Optional;
@@ -74,9 +68,8 @@
private final Choreographer mMainChoreographer;
private final DisplayController mDisplayController;
private final SyncTransactionQueue mSyncQueue;
- private FreeformTaskTransitionStarter mTransitionStarter;
- private Optional<DesktopModeController> mDesktopModeController;
- private Optional<DesktopTasksController> mDesktopTasksController;
+ private final Optional<DesktopModeController> mDesktopModeController;
+ private final Optional<DesktopTasksController> mDesktopTasksController;
private boolean mTransitionDragActive;
private SparseArray<EventReceiver> mEventReceiversByDisplay = new SparseArray<>();
@@ -84,7 +77,8 @@
private final SparseArray<DesktopModeWindowDecoration> mWindowDecorByTaskId =
new SparseArray<>();
private final DragStartListenerImpl mDragStartListener = new DragStartListenerImpl();
- private InputMonitorFactory mInputMonitorFactory;
+ private final InputMonitorFactory mInputMonitorFactory;
+ private TaskOperations mTaskOperations;
public DesktopModeWindowDecorViewModel(
Context context,
@@ -136,7 +130,7 @@
@Override
public void setFreeformTaskTransitionStarter(FreeformTaskTransitionStarter transitionStarter) {
- mTransitionStarter = transitionStarter;
+ mTaskOperations = new TaskOperations(transitionStarter, mContext, mSyncQueue);
}
@Override
@@ -204,13 +198,13 @@
if (decoration == null) return;
decoration.close();
- int displayId = taskInfo.displayId;
+ final int displayId = taskInfo.displayId;
if (mEventReceiversByDisplay.contains(displayId)) {
removeTaskFromEventReceiver(displayId);
}
}
- private class CaptionTouchEventListener implements
+ private class DesktopModeTouchEventListener implements
View.OnClickListener, View.OnTouchListener {
private final int mTaskId;
@@ -220,7 +214,7 @@
private int mDragPointerId = -1;
- private CaptionTouchEventListener(
+ private DesktopModeTouchEventListener(
RunningTaskInfo taskInfo,
DragResizeCallback dragResizeCallback,
DragDetector dragDetector) {
@@ -232,18 +226,12 @@
@Override
public void onClick(View v) {
- DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(mTaskId);
+ final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(mTaskId);
final int id = v.getId();
if (id == R.id.close_window) {
- WindowContainerTransaction wct = new WindowContainerTransaction();
- wct.removeTask(mTaskToken);
- if (Transitions.ENABLE_SHELL_TRANSITIONS) {
- mTransitionStarter.startRemoveTransition(wct);
- } else {
- mSyncQueue.queue(wct);
- }
+ mTaskOperations.closeTask(mTaskToken);
} else if (id == R.id.back_button) {
- injectBackKey();
+ mTaskOperations.injectBackKey();
} else if (id == R.id.caption_handle) {
decoration.createHandleMenu();
} else if (id == R.id.desktop_button) {
@@ -258,29 +246,10 @@
}
}
- private void injectBackKey() {
- sendBackEvent(KeyEvent.ACTION_DOWN);
- sendBackEvent(KeyEvent.ACTION_UP);
- }
-
- private void sendBackEvent(int action) {
- final long when = SystemClock.uptimeMillis();
- final KeyEvent ev = new KeyEvent(when, when, action, KeyEvent.KEYCODE_BACK,
- 0 /* repeat */, 0 /* metaState */, KeyCharacterMap.VIRTUAL_KEYBOARD,
- 0 /* scancode */, KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY,
- InputDevice.SOURCE_KEYBOARD);
-
- ev.setDisplayId(mContext.getDisplay().getDisplayId());
- if (!InputManager.getInstance()
- .injectInputEvent(ev, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC)) {
- Log.e(TAG, "Inject input event fail");
- }
- }
-
@Override
public boolean onTouch(View v, MotionEvent e) {
boolean isDrag = false;
- int id = v.getId();
+ final int id = v.getId();
if (id != R.id.caption_handle && id != R.id.desktop_mode_caption) {
return false;
}
@@ -291,11 +260,11 @@
if (e.getAction() != MotionEvent.ACTION_DOWN) {
return isDrag;
}
- RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId);
+ final RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId);
if (taskInfo.isFocused) {
return isDrag;
}
- WindowContainerTransaction wct = new WindowContainerTransaction();
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
wct.reorder(mTaskToken, true /* onTop */);
mSyncQueue.queue(wct);
return true;
@@ -306,7 +275,7 @@
* @return {@code true} if a drag is happening; or {@code false} if it is not
*/
private void handleEventForMove(MotionEvent e) {
- RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId);
+ final RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId);
if (DesktopModeStatus.isProto2Enabled()
&& taskInfo.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
return;
@@ -325,16 +294,16 @@
break;
}
case MotionEvent.ACTION_MOVE: {
- int dragPointerIdx = e.findPointerIndex(mDragPointerId);
+ final int dragPointerIdx = e.findPointerIndex(mDragPointerId);
mDragResizeCallback.onDragResizeMove(
e.getRawX(dragPointerIdx), e.getRawY(dragPointerIdx));
break;
}
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL: {
- int dragPointerIdx = e.findPointerIndex(mDragPointerId);
- int statusBarHeight = mDisplayController.getDisplayLayout(taskInfo.displayId)
- .stableInsets().top;
+ final int dragPointerIdx = e.findPointerIndex(mDragPointerId);
+ final int statusBarHeight = mDisplayController
+ .getDisplayLayout(taskInfo.displayId).stableInsets().top;
mDragResizeCallback.onDragResizeEnd(
e.getRawX(dragPointerIdx), e.getRawY(dragPointerIdx));
if (e.getRawY(dragPointerIdx) <= statusBarHeight) {
@@ -408,7 +377,7 @@
*/
private void incrementEventReceiverTasks(int displayId) {
if (mEventReceiversByDisplay.contains(displayId)) {
- EventReceiver eventReceiver = mEventReceiversByDisplay.get(displayId);
+ final EventReceiver eventReceiver = mEventReceiversByDisplay.get(displayId);
eventReceiver.incrementTaskNumber();
} else {
createInputChannel(displayId);
@@ -418,7 +387,7 @@
// If all tasks on this display are gone, we don't need to monitor its input.
private void removeTaskFromEventReceiver(int displayId) {
if (!mEventReceiversByDisplay.contains(displayId)) return;
- EventReceiver eventReceiver = mEventReceiversByDisplay.get(displayId);
+ final EventReceiver eventReceiver = mEventReceiversByDisplay.get(displayId);
if (eventReceiver == null) return;
eventReceiver.decrementTaskNumber();
if (eventReceiver.getTasksOnDisplay() == 0) {
@@ -433,7 +402,7 @@
*/
private void handleReceivedMotionEvent(MotionEvent ev, InputMonitor inputMonitor) {
if (DesktopModeStatus.isProto2Enabled()) {
- DesktopModeWindowDecoration focusedDecor = getFocusedDecor();
+ final DesktopModeWindowDecoration focusedDecor = getFocusedDecor();
if (focusedDecor == null
|| focusedDecor.mTaskInfo.getWindowingMode() != WINDOWING_MODE_FREEFORM) {
handleCaptionThroughStatusBar(ev);
@@ -458,9 +427,9 @@
// If an UP/CANCEL action is received outside of caption bounds, turn off handle menu
private void handleEventOutsideFocusedCaption(MotionEvent ev) {
- int action = ev.getActionMasked();
+ final int action = ev.getActionMasked();
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
- DesktopModeWindowDecoration focusedDecor = getFocusedDecor();
+ final DesktopModeWindowDecoration focusedDecor = getFocusedDecor();
if (focusedDecor == null) {
return;
}
@@ -480,7 +449,7 @@
switch (ev.getActionMasked()) {
case MotionEvent.ACTION_DOWN: {
// Begin drag through status bar if applicable.
- DesktopModeWindowDecoration focusedDecor = getFocusedDecor();
+ final DesktopModeWindowDecoration focusedDecor = getFocusedDecor();
if (focusedDecor != null) {
boolean dragFromStatusBarAllowed = false;
if (DesktopModeStatus.isProto2Enabled()) {
@@ -499,14 +468,14 @@
break;
}
case MotionEvent.ACTION_UP: {
- DesktopModeWindowDecoration focusedDecor = getFocusedDecor();
+ final DesktopModeWindowDecoration focusedDecor = getFocusedDecor();
if (focusedDecor == null) {
mTransitionDragActive = false;
return;
}
if (mTransitionDragActive) {
mTransitionDragActive = false;
- int statusBarHeight = mDisplayController
+ final int statusBarHeight = mDisplayController
.getDisplayLayout(focusedDecor.mTaskInfo.displayId).stableInsets().top;
if (ev.getY() > statusBarHeight) {
if (DesktopModeStatus.isProto2Enabled()) {
@@ -530,10 +499,10 @@
@Nullable
private DesktopModeWindowDecoration getFocusedDecor() {
- int size = mWindowDecorByTaskId.size();
+ final int size = mWindowDecorByTaskId.size();
DesktopModeWindowDecoration focusedDecor = null;
for (int i = 0; i < size; i++) {
- DesktopModeWindowDecoration decor = mWindowDecorByTaskId.valueAt(i);
+ final DesktopModeWindowDecoration decor = mWindowDecorByTaskId.valueAt(i);
if (decor != null && decor.isFocused()) {
focusedDecor = decor;
break;
@@ -543,16 +512,16 @@
}
private void createInputChannel(int displayId) {
- InputManager inputManager = InputManager.getInstance();
- InputMonitor inputMonitor =
+ final InputManager inputManager = InputManager.getInstance();
+ final InputMonitor inputMonitor =
mInputMonitorFactory.create(inputManager, mContext);
- EventReceiver eventReceiver = new EventReceiver(inputMonitor,
+ final EventReceiver eventReceiver = new EventReceiver(inputMonitor,
inputMonitor.getInputChannel(), Looper.myLooper());
mEventReceiversByDisplay.put(displayId, eventReceiver);
}
private void disposeInputChannel(int displayId) {
- EventReceiver eventReceiver = mEventReceiversByDisplay.removeReturnOld(displayId);
+ final EventReceiver eventReceiver = mEventReceiversByDisplay.removeReturnOld(displayId);
if (eventReceiver != null) {
eventReceiver.dispose();
}
@@ -571,7 +540,7 @@
SurfaceControl taskSurface,
SurfaceControl.Transaction startT,
SurfaceControl.Transaction finishT) {
- DesktopModeWindowDecoration oldDecoration = mWindowDecorByTaskId.get(taskInfo.taskId);
+ final DesktopModeWindowDecoration oldDecoration = mWindowDecorByTaskId.get(taskInfo.taskId);
if (oldDecoration != null) {
// close the old decoration if it exists to avoid two window decorations being added
oldDecoration.close();
@@ -588,10 +557,10 @@
mSyncQueue);
mWindowDecorByTaskId.put(taskInfo.taskId, windowDecoration);
- TaskPositioner taskPositioner =
+ final TaskPositioner taskPositioner =
new TaskPositioner(mTaskOrganizer, windowDecoration, mDragStartListener);
- CaptionTouchEventListener touchEventListener =
- new CaptionTouchEventListener(
+ final DesktopModeTouchEventListener touchEventListener =
+ new DesktopModeTouchEventListener(
taskInfo, taskPositioner, windowDecoration.getDragDetector());
windowDecoration.setCaptionListeners(touchEventListener, touchEventListener);
windowDecoration.setDragResizeCallback(taskPositioner);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
index 9c2beb9..1a38d24 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
@@ -56,17 +56,14 @@
private View.OnClickListener mOnCaptionButtonClickListener;
private View.OnTouchListener mOnCaptionTouchListener;
private DragResizeCallback mDragResizeCallback;
-
private DragResizeInputListener mDragResizeListener;
+ private final DragDetector mDragDetector;
private RelayoutParams mRelayoutParams = new RelayoutParams();
private final WindowDecoration.RelayoutResult<WindowDecorLinearLayout> mResult =
new WindowDecoration.RelayoutResult<>();
private boolean mDesktopActive;
-
- private DragDetector mDragDetector;
-
private AdditionalWindow mHandleMenu;
DesktopModeWindowDecoration(
@@ -121,14 +118,14 @@
taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM;
final boolean isDragResizeable = isFreeform && taskInfo.isResizeable;
- WindowDecorLinearLayout oldRootView = mResult.mRootView;
+ final WindowDecorLinearLayout oldRootView = mResult.mRootView;
final SurfaceControl oldDecorationSurface = mDecorationContainerSurface;
final WindowContainerTransaction wct = new WindowContainerTransaction();
- int outsetLeftId = R.dimen.freeform_resize_handle;
- int outsetTopId = R.dimen.freeform_resize_handle;
- int outsetRightId = R.dimen.freeform_resize_handle;
- int outsetBottomId = R.dimen.freeform_resize_handle;
+ final int outsetLeftId = R.dimen.freeform_resize_handle;
+ final int outsetTopId = R.dimen.freeform_resize_handle;
+ final int outsetRightId = R.dimen.freeform_resize_handle;
+ final int outsetBottomId = R.dimen.freeform_resize_handle;
mRelayoutParams.reset();
mRelayoutParams.mRunningTaskInfo = taskInfo;
@@ -152,7 +149,7 @@
mRelayoutParams.setCaptionPosition(captionLeft, captionTop);
relayout(mRelayoutParams, startT, finishT, wct, oldRootView, mResult);
- taskInfo = null; // Clear it just in case we use it accidentally
+ // After this line, mTaskInfo is up-to-date and should be used instead of taskInfo
mTaskOrganizer.applyTransaction(wct);
@@ -197,12 +194,13 @@
mDragResizeCallback);
}
- int touchSlop = ViewConfiguration.get(mResult.mRootView.getContext()).getScaledTouchSlop();
+ final int touchSlop = ViewConfiguration.get(mResult.mRootView.getContext())
+ .getScaledTouchSlop();
mDragDetector.setTouchSlop(touchSlop);
- int resize_handle = mResult.mRootView.getResources()
+ final int resize_handle = mResult.mRootView.getResources()
.getDimensionPixelSize(R.dimen.freeform_resize_handle);
- int resize_corner = mResult.mRootView.getResources()
+ final int resize_corner = mResult.mRootView.getResources()
.getDimensionPixelSize(R.dimen.freeform_resize_corner);
mDragResizeListener.setGeometry(
mResult.mWidth, mResult.mHeight, resize_handle, resize_corner, touchSlop);
@@ -212,27 +210,27 @@
* Sets up listeners when a new root view is created.
*/
private void setupRootView() {
- View caption = mResult.mRootView.findViewById(R.id.desktop_mode_caption);
+ final View caption = mResult.mRootView.findViewById(R.id.desktop_mode_caption);
caption.setOnTouchListener(mOnCaptionTouchListener);
- View close = caption.findViewById(R.id.close_window);
+ final View close = caption.findViewById(R.id.close_window);
close.setOnClickListener(mOnCaptionButtonClickListener);
- View back = caption.findViewById(R.id.back_button);
+ final View back = caption.findViewById(R.id.back_button);
back.setOnClickListener(mOnCaptionButtonClickListener);
- View handle = caption.findViewById(R.id.caption_handle);
+ final View handle = caption.findViewById(R.id.caption_handle);
handle.setOnTouchListener(mOnCaptionTouchListener);
handle.setOnClickListener(mOnCaptionButtonClickListener);
updateButtonVisibility();
}
private void setupHandleMenu() {
- View menu = mHandleMenu.mWindowViewHost.getView();
- View fullscreen = menu.findViewById(R.id.fullscreen_button);
+ final View menu = mHandleMenu.mWindowViewHost.getView();
+ final View fullscreen = menu.findViewById(R.id.fullscreen_button);
fullscreen.setOnClickListener(mOnCaptionButtonClickListener);
- View desktop = menu.findViewById(R.id.desktop_button);
+ final View desktop = menu.findViewById(R.id.desktop_button);
desktop.setOnClickListener(mOnCaptionButtonClickListener);
- View split = menu.findViewById(R.id.split_screen_button);
+ final View split = menu.findViewById(R.id.split_screen_button);
split.setOnClickListener(mOnCaptionButtonClickListener);
- View more = menu.findViewById(R.id.more_button);
+ final View more = menu.findViewById(R.id.more_button);
more.setOnClickListener(mOnCaptionButtonClickListener);
}
@@ -242,8 +240,8 @@
* @param visible whether or not the caption should be visible
*/
private void setCaptionVisibility(boolean visible) {
- int v = visible ? View.VISIBLE : View.GONE;
- View captionView = mResult.mRootView.findViewById(R.id.desktop_mode_caption);
+ final int v = visible ? View.VISIBLE : View.GONE;
+ final View captionView = mResult.mRootView.findViewById(R.id.desktop_mode_caption);
captionView.setVisibility(v);
if (!visible) closeHandleMenu();
}
@@ -264,19 +262,19 @@
* Show or hide buttons
*/
void setButtonVisibility(boolean visible) {
- int visibility = visible ? View.VISIBLE : View.GONE;
- View caption = mResult.mRootView.findViewById(R.id.desktop_mode_caption);
- View back = caption.findViewById(R.id.back_button);
- View close = caption.findViewById(R.id.close_window);
+ final int visibility = visible ? View.VISIBLE : View.GONE;
+ final View caption = mResult.mRootView.findViewById(R.id.desktop_mode_caption);
+ final View back = caption.findViewById(R.id.back_button);
+ final View close = caption.findViewById(R.id.close_window);
back.setVisibility(visibility);
close.setVisibility(visibility);
- int buttonTintColorRes =
+ final int buttonTintColorRes =
mDesktopActive ? R.color.decor_button_dark_color
: R.color.decor_button_light_color;
- ColorStateList buttonTintColor =
+ final ColorStateList buttonTintColor =
caption.getResources().getColorStateList(buttonTintColorRes, null /* theme */);
- View handle = caption.findViewById(R.id.caption_handle);
- VectorDrawable handleBackground = (VectorDrawable) handle.getBackground();
+ final View handle = caption.findViewById(R.id.caption_handle);
+ final VectorDrawable handleBackground = (VectorDrawable) handle.getBackground();
handleBackground.setTintList(buttonTintColor);
caption.getBackground().setTint(visible ? Color.WHITE : Color.TRANSPARENT);
}
@@ -297,12 +295,12 @@
* Create and display handle menu window
*/
void createHandleMenu() {
- SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
final Resources resources = mDecorWindowContext.getResources();
- int x = mRelayoutParams.mCaptionX;
- int y = mRelayoutParams.mCaptionY;
- int width = loadDimensionPixelSize(resources, mRelayoutParams.mCaptionWidthId);
- int height = loadDimensionPixelSize(resources, mRelayoutParams.mCaptionHeightId);
+ final int x = mRelayoutParams.mCaptionX;
+ final int y = mRelayoutParams.mCaptionY;
+ final int width = loadDimensionPixelSize(resources, mRelayoutParams.mCaptionWidthId);
+ final int height = loadDimensionPixelSize(resources, mRelayoutParams.mCaptionHeightId);
String namePrefix = "Caption Menu";
mHandleMenu = addWindow(R.layout.desktop_mode_decor_handle_menu, namePrefix, t,
x - mResult.mDecorContainerOffsetX, y - mResult.mDecorContainerOffsetY,
@@ -353,8 +351,8 @@
* @return the point of the input in local space
*/
private PointF offsetCaptionLocation(MotionEvent ev) {
- PointF result = new PointF(ev.getX(), ev.getY());
- Point positionInParent = mTaskOrganizer.getRunningTaskInfo(mTaskInfo.taskId)
+ final PointF result = new PointF(ev.getX(), ev.getY());
+ final Point positionInParent = mTaskOrganizer.getRunningTaskInfo(mTaskInfo.taskId)
.positionInParent;
result.offset(-mRelayoutParams.mCaptionX, -mRelayoutParams.mCaptionY);
result.offset(-positionInParent.x, -positionInParent.y);
@@ -370,8 +368,8 @@
*/
private boolean checkEventInCaptionView(MotionEvent ev, int layoutId) {
if (mResult.mRootView == null) return false;
- PointF inputPoint = offsetCaptionLocation(ev);
- View view = mResult.mRootView.findViewById(layoutId);
+ final PointF inputPoint = offsetCaptionLocation(ev);
+ final View view = mResult.mRootView.findViewById(layoutId);
return view != null && view.pointInView(inputPoint.x, inputPoint.y, 0);
}
@@ -389,20 +387,20 @@
*/
void checkClickEvent(MotionEvent ev) {
if (mResult.mRootView == null) return;
- View caption = mResult.mRootView.findViewById(R.id.desktop_mode_caption);
- PointF inputPoint = offsetCaptionLocation(ev);
+ final View caption = mResult.mRootView.findViewById(R.id.desktop_mode_caption);
+ final PointF inputPoint = offsetCaptionLocation(ev);
if (!isHandleMenuActive()) {
- View handle = caption.findViewById(R.id.caption_handle);
+ final View handle = caption.findViewById(R.id.caption_handle);
clickIfPointInView(inputPoint, handle);
} else {
- View menu = mHandleMenu.mWindowViewHost.getView();
- View fullscreen = menu.findViewById(R.id.fullscreen_button);
+ final View menu = mHandleMenu.mWindowViewHost.getView();
+ final View fullscreen = menu.findViewById(R.id.fullscreen_button);
if (clickIfPointInView(inputPoint, fullscreen)) return;
- View desktop = menu.findViewById(R.id.desktop_button);
+ final View desktop = menu.findViewById(R.id.desktop_button);
if (clickIfPointInView(inputPoint, desktop)) return;
- View split = menu.findViewById(R.id.split_screen_button);
+ final View split = menu.findViewById(R.id.split_screen_button);
if (clickIfPointInView(inputPoint, split)) return;
- View more = menu.findViewById(R.id.more_button);
+ final View more = menu.findViewById(R.id.more_button);
clickIfPointInView(inputPoint, more);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskOperations.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskOperations.java
new file mode 100644
index 0000000..aea3404
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskOperations.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.windowdecor;
+
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+
+import android.app.ActivityManager.RunningTaskInfo;
+import android.content.Context;
+import android.hardware.input.InputManager;
+import android.os.SystemClock;
+import android.util.Log;
+import android.view.InputDevice;
+import android.view.KeyCharacterMap;
+import android.view.KeyEvent;
+import android.window.WindowContainerToken;
+import android.window.WindowContainerTransaction;
+
+import com.android.wm.shell.common.SyncTransactionQueue;
+import com.android.wm.shell.freeform.FreeformTaskTransitionStarter;
+import com.android.wm.shell.transition.Transitions;
+
+/**
+ * Utility class to handle task operations performed on a window decoration.
+ */
+class TaskOperations {
+ private static final String TAG = "TaskOperations";
+
+ private final FreeformTaskTransitionStarter mTransitionStarter;
+ private final Context mContext;
+ private final SyncTransactionQueue mSyncQueue;
+
+ TaskOperations(FreeformTaskTransitionStarter transitionStarter, Context context,
+ SyncTransactionQueue syncQueue) {
+ mTransitionStarter = transitionStarter;
+ mContext = context;
+ mSyncQueue = syncQueue;
+ }
+
+ void injectBackKey() {
+ sendBackEvent(KeyEvent.ACTION_DOWN);
+ sendBackEvent(KeyEvent.ACTION_UP);
+ }
+
+ private void sendBackEvent(int action) {
+ final long when = SystemClock.uptimeMillis();
+ final KeyEvent ev = new KeyEvent(when, when, action, KeyEvent.KEYCODE_BACK,
+ 0 /* repeat */, 0 /* metaState */, KeyCharacterMap.VIRTUAL_KEYBOARD,
+ 0 /* scancode */, KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY,
+ InputDevice.SOURCE_KEYBOARD);
+
+ ev.setDisplayId(mContext.getDisplay().getDisplayId());
+ if (!InputManager.getInstance()
+ .injectInputEvent(ev, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC)) {
+ Log.e(TAG, "Inject input event fail");
+ }
+ }
+
+ void closeTask(WindowContainerToken taskToken) {
+ WindowContainerTransaction wct = new WindowContainerTransaction();
+ wct.removeTask(taskToken);
+ if (Transitions.ENABLE_SHELL_TRANSITIONS) {
+ mTransitionStarter.startRemoveTransition(wct);
+ } else {
+ mSyncQueue.queue(wct);
+ }
+ }
+
+ void minimizeTask(WindowContainerToken taskToken) {
+ WindowContainerTransaction wct = new WindowContainerTransaction();
+ wct.reorder(taskToken, false);
+ if (Transitions.ENABLE_SHELL_TRANSITIONS) {
+ mTransitionStarter.startMinimizedModeTransition(wct);
+ } else {
+ mSyncQueue.queue(wct);
+ }
+ }
+
+ void maximizeTask(RunningTaskInfo taskInfo) {
+ WindowContainerTransaction wct = new WindowContainerTransaction();
+ int targetWindowingMode = taskInfo.getWindowingMode() != WINDOWING_MODE_FULLSCREEN
+ ? WINDOWING_MODE_FULLSCREEN : WINDOWING_MODE_FREEFORM;
+ int displayWindowingMode =
+ taskInfo.configuration.windowConfiguration.getDisplayWindowingMode();
+ wct.setWindowingMode(taskInfo.token,
+ targetWindowingMode == displayWindowingMode
+ ? WINDOWING_MODE_UNDEFINED : targetWindowingMode);
+ if (targetWindowingMode == WINDOWING_MODE_FULLSCREEN) {
+ wct.setBounds(taskInfo.token, null);
+ }
+ if (Transitions.ENABLE_SHELL_TRANSITIONS) {
+ mTransitionStarter.startWindowingModeTransition(targetWindowingMode, wct);
+ } else {
+ mSyncQueue.queue(wct);
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskPositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskPositioner.java
index a49a300..20631f8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskPositioner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskPositioner.java
@@ -47,6 +47,10 @@
private int mCtrlType;
private DragStartListener mDragStartListener;
+ TaskPositioner(ShellTaskOrganizer taskOrganizer, WindowDecoration windowDecoration) {
+ this(taskOrganizer, windowDecoration, dragStartListener -> {});
+ }
+
TaskPositioner(ShellTaskOrganizer taskOrganizer, WindowDecoration windowDecoration,
DragStartListener dragStartListener) {
mTaskOrganizer = taskOrganizer;
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreen.kt
index 7fc12f0..7a86c25 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreen.kt
@@ -18,7 +18,6 @@
import android.content.Context
import android.graphics.Point
-import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
import android.util.DisplayMetrics
import android.view.WindowManager
@@ -74,20 +73,4 @@
open fun testAppIsAlwaysVisible() {
flicker.assertLayers { this.isVisible(testApp) }
}
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
- super.visibleLayersShownMoreThanOneConsecutiveEntry()
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreenCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreenCfArm.kt
new file mode 100644
index 0000000..315e021
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreenCfArm.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.bubble
+
+import com.android.server.wm.flicker.FlickerTest
+import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+class DismissBubbleScreenCfArm(flicker: FlickerTest) : DismissBubbleScreen(flicker)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreenCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreenCfArm.kt
new file mode 100644
index 0000000..26e6273
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreenCfArm.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.bubble
+
+import com.android.server.wm.flicker.FlickerTest
+import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+class ExpandBubbleScreenCfArm(flicker: FlickerTest) : ExpandBubbleScreen(flicker)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleFromLockScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleFromLockScreen.kt
index 08ed91b..379d5e9 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleFromLockScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleFromLockScreen.kt
@@ -94,9 +94,19 @@
flicker.assertLayersEnd { this.isVisible(testApp) }
}
- @Postsubmit @Test fun navBarLayerIsVisibleAtEnd() = flicker.navBarLayerIsVisibleAtEnd()
+ @Postsubmit
+ @Test
+ fun navBarLayerIsVisibleAtEnd() {
+ Assume.assumeFalse(flicker.scenario.isTablet)
+ flicker.navBarLayerIsVisibleAtEnd()
+ }
- @Postsubmit @Test fun navBarLayerPositionAtEnd() = flicker.navBarLayerPositionAtEnd()
+ @Postsubmit
+ @Test
+ fun navBarLayerPositionAtEnd() {
+ Assume.assumeFalse(flicker.scenario.isTablet)
+ flicker.navBarLayerPositionAtEnd()
+ }
/** {@inheritDoc} */
@FlakyTest
@@ -127,42 +137,4 @@
Assume.assumeTrue(flicker.scenario.isGesturalNavigation)
super.navBarWindowIsAlwaysVisible()
}
-
- /** {@inheritDoc} */
- @FlakyTest(bugId = 242088970)
- @Test
- override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @FlakyTest(bugId = 242088970)
- @Test
- override fun statusBarLayerIsVisibleAtStartAndEnd() =
- super.statusBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @FlakyTest(bugId = 242088970)
- @Test
- override fun statusBarLayerPositionAtStartAndEnd() = super.statusBarLayerPositionAtStartAndEnd()
-
- /** {@inheritDoc} */
- @FlakyTest(bugId = 242088970)
- @Test
- override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @FlakyTest(bugId = 242088970)
- @Test
- override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
- super.visibleWindowsShownMoreThanOneConsecutiveEntry()
-
- @FlakyTest(bugId = 251217773)
- @Test
- override fun entireScreenCovered() {
- super.entireScreenCovered()
- }
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreen.kt
index b69ff64..5c0f854 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreen.kt
@@ -16,6 +16,7 @@
package com.android.wm.shell.flicker.bubble
+import android.platform.test.annotations.Presubmit
import androidx.test.filters.RequiresDevice
import androidx.test.uiautomator.By
import androidx.test.uiautomator.Until
@@ -57,6 +58,7 @@
}
}
+ @Presubmit
@Test
open fun testAppIsAlwaysVisible() {
flicker.assertLayers { this.isVisible(testApp) }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreenCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreenCfArm.kt
new file mode 100644
index 0000000..ec6a9c1
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreenCfArm.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.bubble
+
+import com.android.server.wm.flicker.FlickerTest
+import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+open class LaunchBubbleScreenCfArm(flicker: FlickerTest) : LaunchBubbleScreen(flicker)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreenCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreenCfArm.kt
new file mode 100644
index 0000000..69eb06f
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreenCfArm.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.bubble
+
+import com.android.server.wm.flicker.FlickerTest
+import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+open class MultiBubblesScreenCfArm(flicker: FlickerTest) : MultiBubblesScreen(flicker)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt
index bc9fc73..8a694f7 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt
@@ -52,7 +52,7 @@
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class EnterPipOnUserLeaveHintTest(flicker: FlickerTest) : EnterPipTest(flicker) {
+open class EnterPipOnUserLeaveHintTest(flicker: FlickerTest) : EnterPipTest(flicker) {
/** Defines the transition used to run the test */
override val transition: FlickerBuilder.() -> Unit
get() = {
@@ -61,6 +61,8 @@
pipApp.enableEnterPipOnUserLeaveHint()
}
teardown {
+ // close gracefully so that onActivityUnpinned() can be called before force exit
+ pipApp.closePipWindow(wmHelper)
pipApp.exit(wmHelper)
}
transitions { tapl.goHome() }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTestCfArm.kt
new file mode 100644
index 0000000..e478050
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTestCfArm.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.pip
+
+import com.android.server.wm.flicker.FlickerTest
+import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import org.junit.FixMethodOrder
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/** This test will fail because of b/264261596 */
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class EnterPipOnUserLeaveHintTestCfArm(flicker: FlickerTest) : EnterPipOnUserLeaveHintTest(flicker)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
index 1524b16..5d7003f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
@@ -59,12 +59,8 @@
/** {@inheritDoc} */
override val transition: FlickerBuilder.() -> Unit
get() = {
- setup {
- pipApp.launchViaIntent(wmHelper)
- }
- teardown {
- pipApp.exit(wmHelper)
- }
+ setup { pipApp.launchViaIntent(wmHelper) }
+ teardown { pipApp.exit(wmHelper) }
transitions { pipApp.clickEnterPipButton(wmHelper) }
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTestCfArm.kt
new file mode 100644
index 0000000..d2e8645
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTestCfArm.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.pip
+
+import com.android.server.wm.flicker.FlickerTest
+import com.android.server.wm.flicker.FlickerTestFactory
+import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import com.android.server.wm.traces.common.service.PlatformConsts
+import org.junit.FixMethodOrder
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class EnterPipTestCfArm(flicker: FlickerTest) : EnterPipTest(flicker) {
+ companion object {
+ /**
+ * Creates the test configurations.
+ *
+ * See [FlickerTestFactory.nonRotationTests] for configuring repetitions, screen orientation
+ * and navigation modes.
+ */
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): List<FlickerTest> {
+ return FlickerTestFactory.nonRotationTests(
+ supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ )
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
index da16240..02d50f4 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
@@ -17,7 +17,7 @@
package com.android.wm.shell.flicker.pip
import android.app.Activity
-import android.platform.test.annotations.FlakyTest
+import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.FlickerBuilder
@@ -27,7 +27,6 @@
import com.android.server.wm.flicker.helpers.FixedOrientationAppHelper
import com.android.server.wm.flicker.helpers.WindowUtils
import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.flicker.navBarLayerPositionAtStartAndEnd
import com.android.server.wm.flicker.testapp.ActivityOptions.Pip.ACTION_ENTER_PIP
import com.android.server.wm.flicker.testapp.ActivityOptions.PortraitOnlyActivity.EXTRA_FIXED_ORIENTATION
import com.android.server.wm.traces.common.ComponentNameMatcher
@@ -67,7 +66,7 @@
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class EnterPipToOtherOrientationTest(flicker: FlickerTest) : PipTransition(flicker) {
+open class EnterPipToOtherOrientationTest(flicker: FlickerTest) : PipTransition(flicker) {
private val testApp = FixedOrientationAppHelper(instrumentation)
private val startingBounds = WindowUtils.getDisplayBounds(PlatformConsts.Rotation.ROTATION_90)
private val endingBounds = WindowUtils.getDisplayBounds(PlatformConsts.Rotation.ROTATION_0)
@@ -116,14 +115,6 @@
}
/**
- * Checks that the [ComponentNameMatcher.NAV_BAR] has the correct position at the start and end
- * of the transition
- */
- @FlakyTest
- @Test
- override fun navBarLayerPositionAtStartAndEnd() = flicker.navBarLayerPositionAtStartAndEnd()
-
- /**
* Checks that all parts of the screen are covered at the start and end of the transition
*
* TODO b/197726599 Prevents all states from being checked
@@ -132,12 +123,6 @@
@Test
fun entireScreenCoveredAtStartAndEnd() = flicker.entireScreenCovered(allStates = false)
- @FlakyTest(bugId = 251219769)
- @Test
- override fun entireScreenCovered() {
- super.entireScreenCovered()
- }
-
/** Checks [pipApp] window remains visible and on top throughout the transition */
@Presubmit
@Test
@@ -180,10 +165,25 @@
@Presubmit
@Test
fun pipAppLayerCoversFullScreenOnStart() {
+ Assume.assumeFalse(tapl.isTablet)
flicker.assertLayersStart { visibleRegion(pipApp).coversExactly(startingBounds) }
}
/**
+ * Checks that the visible region of [pipApp] covers the full display area at the start of the
+ * transition
+ */
+ @Postsubmit
+ @Test
+ fun pipAppLayerPlusLetterboxCoversFullScreenOnStartTablet() {
+ Assume.assumeFalse(tapl.isTablet)
+ flicker.assertLayersStart {
+ visibleRegion(pipApp.or(ComponentNameMatcher.LETTERBOX))
+ .coversExactly(startingBounds)
+ }
+ }
+
+ /**
* Checks that the visible region of [testApp] plus the visible region of [pipApp] cover the
* full display area at the end of the transition
*/
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTestCfArm.kt
new file mode 100644
index 0000000..39aab6e
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTestCfArm.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.pip
+
+import com.android.server.wm.flicker.FlickerTest
+import com.android.server.wm.flicker.FlickerTestFactory
+import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import com.android.server.wm.traces.common.service.PlatformConsts
+import org.junit.FixMethodOrder
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/** This test fails because of b/264261596 */
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+open class EnterPipToOtherOrientationTestCfArm(flicker: FlickerTest) :
+ EnterPipToOtherOrientationTest(flicker) {
+ companion object {
+ /**
+ * Creates the test configurations.
+ *
+ * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
+ * navigation modes.
+ */
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): Collection<FlickerTest> {
+ return FlickerTestFactory.nonRotationTests(
+ supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ )
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt
index 1420f8ce..3bfcde3 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt
@@ -22,8 +22,10 @@
import com.android.server.wm.flicker.FlickerBuilder
import com.android.server.wm.flicker.FlickerTest
import com.android.server.wm.flicker.FlickerTestFactory
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import com.android.server.wm.traces.common.service.PlatformConsts
+import org.junit.Assume
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -56,7 +58,7 @@
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class ExitPipViaExpandButtonClickTest(flicker: FlickerTest) : ExitPipToAppTransition(flicker) {
+open class ExitPipViaExpandButtonClickTest(flicker: FlickerTest) : ExitPipToAppTransition(flicker) {
/** Defines the transition used to run the test */
override val transition: FlickerBuilder.() -> Unit
@@ -74,10 +76,19 @@
}
/** {@inheritDoc} */
- @Presubmit @Test override fun entireScreenCovered() = super.entireScreenCovered()
+ @FlakyTest(bugId = 197726610)
+ @Test
+ override fun pipLayerExpands() {
+ Assume.assumeFalse(isShellTransitionsEnabled)
+ super.pipLayerExpands()
+ }
- /** {@inheritDoc} */
- @FlakyTest(bugId = 197726610) @Test override fun pipLayerExpands() = super.pipLayerExpands()
+ @Presubmit
+ @Test
+ fun pipLayerExpands_ShellTransit() {
+ Assume.assumeTrue(isShellTransitionsEnabled)
+ super.pipLayerExpands()
+ }
companion object {
/**
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTestCfArm.kt
new file mode 100644
index 0000000..f77e335
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTestCfArm.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.pip
+
+import com.android.server.wm.flicker.FlickerTest
+import com.android.server.wm.flicker.FlickerTestFactory
+import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import com.android.server.wm.traces.common.service.PlatformConsts
+import org.junit.FixMethodOrder
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class ExitPipViaExpandButtonClickTestCfArm(flicker: FlickerTest) :
+ ExitPipViaExpandButtonClickTest(flicker) {
+ companion object {
+ /**
+ * Creates the test configurations.
+ *
+ * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
+ * navigation modes.
+ */
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): List<FlickerTest> {
+ return FlickerTestFactory.nonRotationTests(
+ supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ )
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt
index dffbe7e..2c5455f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt
@@ -57,7 +57,7 @@
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class ExitPipViaIntentTest(flicker: FlickerTest) : ExitPipToAppTransition(flicker) {
+open class ExitPipViaIntentTest(flicker: FlickerTest) : ExitPipToAppTransition(flicker) {
/** Defines the transition used to run the test */
override val transition: FlickerBuilder.() -> Unit
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTestCfArm.kt
new file mode 100644
index 0000000..03dfa5b
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTestCfArm.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.pip
+
+import com.android.server.wm.flicker.FlickerTest
+import com.android.server.wm.flicker.FlickerTestFactory
+import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import com.android.server.wm.traces.common.service.PlatformConsts
+import org.junit.FixMethodOrder
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class ExitPipViaIntentTestCfArm(flicker: FlickerTest) : ExitPipViaIntentTest(flicker) {
+ companion object {
+ /**
+ * Creates the test configurations.
+ *
+ * See [FlickerTestFactory.nonRotationTests] for configuring repetitions, screen orientation
+ * and navigation modes.
+ */
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): List<FlickerTest> {
+ return FlickerTestFactory.nonRotationTests(
+ supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ )
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTest.kt
index 232c025..8a1a31a 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTest.kt
@@ -54,7 +54,7 @@
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class ExitPipWithDismissButtonTest(flicker: FlickerTest) : ExitPipTransition(flicker) {
+open class ExitPipWithDismissButtonTest(flicker: FlickerTest) : ExitPipTransition(flicker) {
override val transition: FlickerBuilder.() -> Unit
get() = {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTestCfArm.kt
new file mode 100644
index 0000000..a3f214c
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTestCfArm.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.pip
+
+import com.android.server.wm.flicker.FlickerTest
+import com.android.server.wm.flicker.FlickerTestFactory
+import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import com.android.server.wm.traces.common.service.PlatformConsts
+import org.junit.FixMethodOrder
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+open class ExitPipWithDismissButtonTestCfArm(flicker: FlickerTest) :
+ ExitPipWithDismissButtonTest(flicker) {
+ companion object {
+ /**
+ * Creates the test configurations.
+ *
+ * See [FlickerTestFactory.nonRotationTests] for configuring repetitions, screen orientation
+ * and navigation modes.
+ */
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): List<FlickerTest> {
+ return FlickerTestFactory.nonRotationTests(
+ supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ )
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithSwipeDownTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithSwipeDownTest.kt
index dbbfdcc..54ad991 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithSwipeDownTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithSwipeDownTest.kt
@@ -54,7 +54,7 @@
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class ExitPipWithSwipeDownTest(flicker: FlickerTest) : ExitPipTransition(flicker) {
+open class ExitPipWithSwipeDownTest(flicker: FlickerTest) : ExitPipTransition(flicker) {
override val transition: FlickerBuilder.() -> Unit
get() = {
super.transition(this)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithSwipeDownTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithSwipeDownTestCfArm.kt
new file mode 100644
index 0000000..9f26018
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithSwipeDownTestCfArm.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.pip
+
+import com.android.server.wm.flicker.FlickerTest
+import com.android.server.wm.flicker.FlickerTestFactory
+import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import com.android.server.wm.traces.common.service.PlatformConsts
+import org.junit.FixMethodOrder
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class ExitPipWithSwipeDownTestCfArm(flicker: FlickerTest) : ExitPipWithSwipeDownTest(flicker) {
+ companion object {
+ /**
+ * Creates the test configurations.
+ *
+ * See [FlickerTestFactory.nonRotationTests] for configuring repetitions, screen orientation
+ * and navigation modes.
+ */
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): List<FlickerTest> {
+ return FlickerTestFactory.nonRotationTests(
+ supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ )
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
index f213cc9..eff2df8 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
@@ -16,7 +16,7 @@
package com.android.wm.shell.flicker.pip
-import android.platform.test.annotations.FlakyTest
+import android.platform.test.annotations.Presubmit
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.FlickerBuilder
import com.android.server.wm.flicker.FlickerTest
@@ -54,7 +54,7 @@
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class ExpandPipOnDoubleClickTest(flicker: FlickerTest) : PipTransition(flicker) {
+open class ExpandPipOnDoubleClickTest(flicker: FlickerTest) : PipTransition(flicker) {
override val transition: FlickerBuilder.() -> Unit
get() = buildTransition { transitions { pipApp.doubleClickPipWindow(wmHelper) } }
@@ -62,7 +62,7 @@
* Checks that the pip app window remains inside the display bounds throughout the whole
* animation
*/
- @FlakyTest(bugId = 249308003)
+ @Presubmit
@Test
fun pipWindowRemainInsideVisibleBounds() {
flicker.assertWmVisibleRegion(pipApp) { coversAtMost(displayBounds) }
@@ -72,28 +72,28 @@
* Checks that the pip app layer remains inside the display bounds throughout the whole
* animation
*/
- @FlakyTest(bugId = 249308003)
+ @Presubmit
@Test
fun pipLayerRemainInsideVisibleBounds() {
flicker.assertLayersVisibleRegion(pipApp) { coversAtMost(displayBounds) }
}
/** Checks [pipApp] window remains visible throughout the animation */
- @FlakyTest(bugId = 249308003)
+ @Presubmit
@Test
fun pipWindowIsAlwaysVisible() {
flicker.assertWm { isAppWindowVisible(pipApp) }
}
/** Checks [pipApp] layer remains visible throughout the animation */
- @FlakyTest(bugId = 249308003)
+ @Presubmit
@Test
fun pipLayerIsAlwaysVisible() {
flicker.assertLayers { isVisible(pipApp) }
}
/** Checks that the visible region of [pipApp] always expands during the animation */
- @FlakyTest(bugId = 249308003)
+ @Presubmit
@Test
fun pipLayerExpands() {
flicker.assertLayers {
@@ -104,7 +104,7 @@
}
}
- @FlakyTest(bugId = 249308003)
+ @Presubmit
@Test
fun pipSameAspectRatio() {
flicker.assertLayers {
@@ -116,92 +116,26 @@
}
/** Checks [pipApp] window remains pinned throughout the animation */
- @FlakyTest(bugId = 249308003)
+ @Presubmit
@Test
fun windowIsAlwaysPinned() {
flicker.assertWm { this.invoke("hasPipWindow") { it.isPinned(pipApp) } }
}
- /** Checks [ComponentMatcher.LAUNCHER] layer remains visible throughout the animation */
- @FlakyTest(bugId = 249308003)
+ /** Checks [ComponentNameMatcher.LAUNCHER] layer remains visible throughout the animation */
+ @Presubmit
@Test
fun launcherIsAlwaysVisible() {
flicker.assertLayers { isVisible(ComponentNameMatcher.LAUNCHER) }
}
/** Checks that the focus doesn't change between windows during the transition */
- @FlakyTest(bugId = 216306753)
+ @Presubmit
@Test
fun focusDoesNotChange() {
flicker.assertEventLog { this.focusDoesNotChange() }
}
- @FlakyTest(bugId = 216306753)
- @Test
- override fun navBarLayerIsVisibleAtStartAndEnd() {
- super.navBarLayerIsVisibleAtStartAndEnd()
- }
-
- @FlakyTest(bugId = 216306753)
- @Test
- override fun navBarWindowIsAlwaysVisible() {
- super.navBarWindowIsAlwaysVisible()
- }
-
- @FlakyTest(bugId = 216306753)
- @Test
- override fun statusBarLayerIsVisibleAtStartAndEnd() {
- super.statusBarLayerIsVisibleAtStartAndEnd()
- }
-
- @FlakyTest(bugId = 216306753)
- @Test
- override fun statusBarLayerPositionAtStartAndEnd() {
- super.statusBarLayerPositionAtStartAndEnd()
- }
-
- @FlakyTest(bugId = 216306753)
- @Test
- override fun taskBarLayerIsVisibleAtStartAndEnd() {
- super.taskBarLayerIsVisibleAtStartAndEnd()
- }
-
- @FlakyTest(bugId = 216306753)
- @Test
- override fun taskBarWindowIsAlwaysVisible() {
- super.taskBarWindowIsAlwaysVisible()
- }
-
- @FlakyTest(bugId = 216306753)
- @Test
- override fun visibleLayersShownMoreThanOneConsecutiveEntry() {
- super.visibleLayersShownMoreThanOneConsecutiveEntry()
- }
-
- @FlakyTest(bugId = 216306753)
- @Test
- override fun statusBarWindowIsAlwaysVisible() {
- super.statusBarWindowIsAlwaysVisible()
- }
-
- @FlakyTest(bugId = 216306753)
- @Test
- override fun visibleWindowsShownMoreThanOneConsecutiveEntry() {
- super.visibleWindowsShownMoreThanOneConsecutiveEntry()
- }
-
- @FlakyTest(bugId = 216306753)
- @Test
- override fun entireScreenCovered() {
- super.entireScreenCovered()
- }
-
- @FlakyTest(bugId = 216306753)
- @Test
- override fun navBarLayerPositionAtStartAndEnd() {
- super.navBarLayerPositionAtStartAndEnd()
- }
-
companion object {
/**
* Creates the test configurations.
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTestCfArm.kt
new file mode 100644
index 0000000..5feb73e
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTestCfArm.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.pip
+
+import com.android.server.wm.flicker.FlickerTest
+import com.android.server.wm.flicker.FlickerTestFactory
+import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import com.android.server.wm.traces.common.service.PlatformConsts
+import org.junit.FixMethodOrder
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class ExpandPipOnDoubleClickTestCfArm(flicker: FlickerTest) : ExpandPipOnDoubleClickTest(flicker) {
+ companion object {
+ /**
+ * Creates the test configurations.
+ *
+ * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
+ * navigation modes.
+ */
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): List<FlickerTest> {
+ return FlickerTestFactory.nonRotationTests(
+ supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ )
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnPinchOpenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnPinchOpenTest.kt
index 34f6659..fcb8af4 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnPinchOpenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnPinchOpenTest.kt
@@ -16,7 +16,7 @@
package com.android.wm.shell.flicker.pip
-import android.platform.test.annotations.Postsubmit
+import android.platform.test.annotations.Presubmit
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.FlickerBuilder
import com.android.server.wm.flicker.FlickerTest
@@ -34,12 +34,12 @@
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class ExpandPipOnPinchOpenTest(flicker: FlickerTest) : PipTransition(flicker) {
+open class ExpandPipOnPinchOpenTest(flicker: FlickerTest) : PipTransition(flicker) {
override val transition: FlickerBuilder.() -> Unit
get() = buildTransition { transitions { pipApp.pinchOpenPipWindow(wmHelper, 0.4f, 30) } }
/** Checks that the visible region area of [pipApp] always increases during the animation. */
- @Postsubmit
+ @Presubmit
@Test
fun pipLayerAreaIncreases() {
flicker.assertLayers {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnPinchOpenTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnPinchOpenTestCfArm.kt
new file mode 100644
index 0000000..30050bf
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnPinchOpenTestCfArm.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.pip
+
+import com.android.server.wm.flicker.FlickerTest
+import com.android.server.wm.flicker.FlickerTestFactory
+import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import com.android.server.wm.traces.common.service.PlatformConsts
+import org.junit.FixMethodOrder
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class ExpandPipOnPinchOpenTestCfArm(flicker: FlickerTest) : ExpandPipOnPinchOpenTest(flicker) {
+ companion object {
+ /**
+ * Creates the test configurations.
+ *
+ * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
+ * navigation modes.
+ */
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): List<FlickerTest> {
+ return FlickerTestFactory.nonRotationTests(
+ supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ )
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
index 737e65c..3939e7f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
@@ -56,9 +56,7 @@
imeApp.launchViaIntent(wmHelper)
setRotation(flicker.scenario.startRotation)
}
- teardown {
- imeApp.exit(wmHelper)
- }
+ teardown { imeApp.exit(wmHelper) }
transitions {
// open the soft keyboard
imeApp.openIME(wmHelper)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTestCfArm.kt
new file mode 100644
index 0000000..9e2d27d
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTestCfArm.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.pip
+
+import com.android.server.wm.flicker.FlickerTest
+import com.android.server.wm.flicker.FlickerTestFactory
+import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import com.android.server.wm.traces.common.service.PlatformConsts
+import org.junit.FixMethodOrder
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class PipKeyboardTestCfArm(flicker: FlickerTest) : PipKeyboardTest(flicker) {
+ companion object {
+ private const val TAG_IME_VISIBLE = "imeIsVisible"
+
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): Collection<FlickerTest> {
+ return FlickerTestFactory.nonRotationTests(
+ supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ )
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
index eee00bd..4557a15 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.flicker.pip
-import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Presubmit
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.FlickerBuilder
@@ -24,11 +23,8 @@
import com.android.server.wm.flicker.FlickerTestFactory
import com.android.server.wm.flicker.helpers.SimpleAppHelper
import com.android.server.wm.flicker.helpers.WindowUtils
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.helpers.setRotation
import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import org.junit.Assume
-import org.junit.Before
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -66,11 +62,6 @@
private val screenBoundsStart = WindowUtils.getDisplayBounds(flicker.scenario.startRotation)
private val screenBoundsEnd = WindowUtils.getDisplayBounds(flicker.scenario.endRotation)
- @Before
- open fun before() {
- Assume.assumeFalse(isShellTransitionsEnabled)
- }
-
override val transition: FlickerBuilder.() -> Unit
get() = buildTransition {
setup {
@@ -80,11 +71,6 @@
transitions { setRotation(flicker.scenario.endRotation) }
}
- /** Checks the position of the navigation bar at the start and end of the transition */
- @FlakyTest(bugId = 240499181)
- @Test
- override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
-
/** Checks that [testApp] layer is within [screenBoundsStart] at the start of the transition */
@Presubmit
@Test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTestCfArm.kt
new file mode 100644
index 0000000..e72d604
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTestCfArm.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.pip
+
+import com.android.server.wm.flicker.FlickerTest
+import com.android.server.wm.flicker.FlickerTestFactory
+import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import org.junit.FixMethodOrder
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class PipRotationTestCfArm(flicker: FlickerTest) : PipRotationTest(flicker) {
+ companion object {
+ /**
+ * Creates the test configurations.
+ *
+ * See [FlickerTestFactory.nonRotationTests] for configuring repetitions, screen orientation
+ * and navigation modes.
+ */
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): Collection<FlickerTest> {
+ return FlickerTestFactory.rotationTests()
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest_ShellTransit.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest_ShellTransit.kt
deleted file mode 100644
index d0d9167..0000000
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest_ShellTransit.kt
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.flicker.pip
-
-import android.platform.test.annotations.FlakyTest
-import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import org.junit.Assume
-import org.junit.Before
-import org.junit.FixMethodOrder
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-/**
- * Test Pip Stack in bounds after rotations.
- *
- * To run this test: `atest WMShellFlickerTests:PipRotationTest_ShellTransit`
- *
- * Actions:
- * ```
- * Launch a [pipApp] in pip mode
- * Launch another app [fixedApp] (appears below pip)
- * Rotate the screen from [flicker.scenario.startRotation] to [flicker.scenario.endRotation]
- * (usually, 0->90 and 90->0)
- * ```
- * Notes:
- * ```
- * 1. Some default assertions (e.g., nav bar, status bar and screen covered)
- * are inherited from [PipTransition]
- * 2. Part of the test setup occurs automatically via
- * [com.android.server.wm.flicker.TransitionRunnerWithRules],
- * including configuring navigation mode, initial orientation and ensuring no
- * apps are running before setup
- * ```
- */
-@RequiresDevice
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-@FlakyTest(bugId = 239575053)
-class PipRotationTest_ShellTransit(flicker: FlickerTest) : PipRotationTest(flicker) {
- @Before
- override fun before() {
- Assume.assumeTrue(isShellTransitionsEnabled)
- }
-
- /** {@inheritDoc} */
- @FlakyTest
- @Test
- override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
-}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt
index a9fe93d..ce31aac 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt
@@ -18,6 +18,7 @@
import android.app.Instrumentation
import android.content.Intent
+import android.platform.test.annotations.Postsubmit
import com.android.server.wm.flicker.FlickerBuilder
import com.android.server.wm.flicker.FlickerTest
import com.android.server.wm.flicker.helpers.PipAppHelper
@@ -25,8 +26,11 @@
import com.android.server.wm.flicker.helpers.setRotation
import com.android.server.wm.flicker.rules.RemoveAllTasksButHomeRule.Companion.removeAllTasksButHome
import com.android.server.wm.flicker.testapp.ActivityOptions
+import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.common.service.PlatformConsts
import com.android.wm.shell.flicker.BaseTest
+import com.google.common.truth.Truth
+import org.junit.Test
abstract class PipTransition(flicker: FlickerTest) : BaseTest(flicker) {
protected val pipApp = PipAppHelper(instrumentation)
@@ -56,7 +60,6 @@
* Gets a configuration that handles basic setup and teardown of pip tests and that launches the
* Pip app for test
*
- * @param eachRun If the pip app should be launched in each run (otherwise only 1x per test)
* @param stringExtras Arguments to pass to the PIP launch intent
* @param extraSpec Additional segment of flicker specification
*/
@@ -71,11 +74,25 @@
removeAllTasksButHome()
pipApp.launchViaIntentAndWaitForPip(wmHelper, stringExtras = stringExtras)
}
- teardown {
- pipApp.exit(wmHelper)
- }
+ teardown { pipApp.exit(wmHelper) }
extraSpec(this)
}
}
+
+ @Postsubmit
+ @Test
+ fun hasAtMostOnePipDismissOverlayWindow() {
+ val matcher = ComponentNameMatcher("", "pip-dismiss-overlay")
+ flicker.assertWm {
+ val overlaysPerState =
+ trace.entries.map { entry ->
+ entry.windowStates.count { window -> matcher.windowMatchesAnyOf(window) } <= 1
+ }
+
+ Truth.assertWithMessage("Number of dismiss overlays per state")
+ .that(overlaysPerState)
+ .doesNotContain(false)
+ }
+ }
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt
index d7107db..871515b 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt
@@ -25,7 +25,6 @@
import com.android.server.wm.flicker.FlickerTest
import com.android.server.wm.flicker.FlickerTestFactory
import com.android.server.wm.flicker.helpers.WindowUtils
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.testapp.ActivityOptions
import com.android.server.wm.flicker.testapp.ActivityOptions.PortraitOnlyActivity.EXTRA_FIXED_ORIENTATION
@@ -104,22 +103,6 @@
flicker.assertWmEnd { hasRotation(PlatformConsts.Rotation.ROTATION_90) }
}
- /** {@inheritDoc} */
- @Presubmit
- @Test
- override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Presubmit
- @Test
- override fun statusBarLayerIsVisibleAtStartAndEnd() =
- super.statusBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @FlakyTest
- @Test
- override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
-
@Presubmit
@Test
fun pipWindowInsideDisplay() {
@@ -132,22 +115,10 @@
flicker.assertWmEnd { isAppWindowOnTop(pipApp) }
}
- private fun pipLayerInsideDisplay_internal() {
- flicker.assertLayersStart { visibleRegion(pipApp).coversAtMost(startingBounds) }
- }
-
@Presubmit
@Test
fun pipLayerInsideDisplay() {
- Assume.assumeFalse(isShellTransitionsEnabled)
- pipLayerInsideDisplay_internal()
- }
-
- @FlakyTest(bugId = 250527829)
- @Test
- fun pipLayerInsideDisplay_shellTransit() {
- Assume.assumeTrue(isShellTransitionsEnabled)
- pipLayerInsideDisplay_internal()
+ flicker.assertLayersStart { visibleRegion(pipApp).coversAtMost(startingBounds) }
}
@Presubmit
@@ -173,7 +144,9 @@
override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
- @Postsubmit @Test override fun entireScreenCovered() = super.entireScreenCovered()
+ @FlakyTest(bugId = 264243884)
+ @Test
+ override fun entireScreenCovered() = super.entireScreenCovered()
companion object {
@Parameterized.Parameters(name = "{0}")
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipMenuTests.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipMenuTests.kt
index 7403aab..0432a84 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipMenuTests.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipMenuTests.kt
@@ -31,22 +31,26 @@
@RequiresDevice
class TvPipMenuTests : TvPipTestBase() {
- private val systemUiResources =
+ private val systemUiResources by lazy {
packageManager.getResourcesForApplication(SYSTEM_UI_PACKAGE_NAME)
- private val pipBoundsWhileInMenu: Rect =
+ }
+ private val pipBoundsWhileInMenu: Rect by lazy {
systemUiResources.run {
val bounds =
getString(getIdentifier("pip_menu_bounds", "string", SYSTEM_UI_PACKAGE_NAME))
Rect.unflattenFromString(bounds) ?: error("Could not retrieve PiP menu bounds")
}
- private val playButtonDescription =
+ }
+ private val playButtonDescription by lazy {
systemUiResources.run {
getString(getIdentifier("pip_play", "string", SYSTEM_UI_PACKAGE_NAME))
}
- private val pauseButtonDescription =
+ }
+ private val pauseButtonDescription by lazy {
systemUiResources.run {
getString(getIdentifier("pip_pause", "string", SYSTEM_UI_PACKAGE_NAME))
}
+ }
@Before
fun tvPipMenuTestsTestUp() {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt
index 65cbea0..c08ad69 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.flicker.splitscreen
-import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.IwTest
import android.platform.test.annotations.Presubmit
import androidx.test.filters.RequiresDevice
@@ -116,46 +115,6 @@
/** {@inheritDoc} */
@Presubmit @Test override fun entireScreenCovered() = super.entireScreenCovered()
- /** {@inheritDoc} */
- @Presubmit
- @Test
- override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @FlakyTest(bugId = 206753786)
- @Test
- override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Presubmit
- @Test
- override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Presubmit
- @Test
- override fun statusBarLayerIsVisibleAtStartAndEnd() =
- super.statusBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Presubmit
- @Test
- override fun statusBarLayerPositionAtStartAndEnd() = super.statusBarLayerPositionAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Presubmit
- @Test
- override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Presubmit
- @Test
- override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Presubmit
- @Test
- override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
@Presubmit
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt
index fcdad96..514365f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt
@@ -18,7 +18,6 @@
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.IwTest
-import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.FlickerBuilder
@@ -149,60 +148,9 @@
)
/** {@inheritDoc} */
- @Postsubmit @Test override fun entireScreenCovered() = super.entireScreenCovered()
-
- /** {@inheritDoc} */
- @Postsubmit
+ @FlakyTest(bugId = 263213649)
@Test
- override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarLayerIsVisibleAtStartAndEnd() =
- super.statusBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarLayerPositionAtStartAndEnd() = super.statusBarLayerPositionAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
- super.visibleLayersShownMoreThanOneConsecutiveEntry()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
- super.visibleWindowsShownMoreThanOneConsecutiveEntry()
+ override fun entireScreenCovered() = super.entireScreenCovered()
companion object {
@Parameterized.Parameters(name = "{0}")
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromShortcut.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromShortcut.kt
index af63f7c..d086f7e 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromShortcut.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromShortcut.kt
@@ -16,8 +16,8 @@
package com.android.wm.shell.flicker.splitscreen
+import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.IwTest
-import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.FlickerBuilder
@@ -126,60 +126,9 @@
}
/** {@inheritDoc} */
- @Postsubmit @Test override fun entireScreenCovered() = super.entireScreenCovered()
-
- /** {@inheritDoc} */
- @Postsubmit
+ @FlakyTest(bugId = 241523824)
@Test
- override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarLayerIsVisibleAtStartAndEnd() =
- super.statusBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarLayerPositionAtStartAndEnd() = super.statusBarLayerPositionAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
- super.visibleLayersShownMoreThanOneConsecutiveEntry()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
- super.visibleWindowsShownMoreThanOneConsecutiveEntry()
+ override fun entireScreenCovered() = super.entireScreenCovered()
companion object {
@Parameterized.Parameters(name = "{0}")
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenFromOverview.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenFromOverview.kt
index c09ca91..a9cbb74 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenFromOverview.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenFromOverview.kt
@@ -18,13 +18,11 @@
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.IwTest
-import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.FlickerBuilder
import com.android.server.wm.flicker.FlickerTest
import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import com.android.wm.shell.flicker.appWindowBecomesVisible
import com.android.wm.shell.flicker.layerBecomesVisible
@@ -33,7 +31,6 @@
import com.android.wm.shell.flicker.splitAppLayerBoundsIsVisibleAtEnd
import com.android.wm.shell.flicker.splitScreenDividerBecomesVisible
import com.android.wm.shell.flicker.splitScreenEntered
-import org.junit.Assume
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -96,18 +93,6 @@
@Presubmit
@Test
fun secondaryAppBoundsBecomesVisible() {
- Assume.assumeFalse(isShellTransitionsEnabled)
- flicker.splitAppLayerBoundsBecomesVisible(
- secondaryApp,
- landscapePosLeft = !tapl.isTablet,
- portraitPosTop = true
- )
- }
-
- @FlakyTest(bugId = 244407465)
- @Test
- fun secondaryAppBoundsBecomesVisible_shellTransit() {
- Assume.assumeTrue(isShellTransitionsEnabled)
flicker.splitAppLayerBoundsBecomesVisible(
secondaryApp,
landscapePosLeft = !tapl.isTablet,
@@ -129,58 +114,11 @@
override fun entireScreenCovered() = super.entireScreenCovered()
/** {@inheritDoc} */
- @Presubmit
- @Test
- override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Presubmit
- @Test
- override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Presubmit
- @Test
- override fun statusBarLayerIsVisibleAtStartAndEnd() =
- super.statusBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Presubmit
- @Test
- override fun statusBarLayerPositionAtStartAndEnd() = super.statusBarLayerPositionAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Presubmit
- @Test
- override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Presubmit
- @Test
- override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Presubmit
- @Test
- override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
@FlakyTest(bugId = 252736515)
@Test
override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
super.visibleLayersShownMoreThanOneConsecutiveEntry()
- /** {@inheritDoc} */
- @Presubmit
- @Test
- override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
- super.visibleWindowsShownMoreThanOneConsecutiveEntry()
-
companion object {
@Parameterized.Parameters(name = "{0}")
@JvmStatic
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt
index 09568b2..c7b81d9 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt
@@ -196,56 +196,9 @@
/** {@inheritDoc} */
@Postsubmit
@Test
- override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarLayerIsVisibleAtStartAndEnd() =
- super.statusBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarLayerPositionAtStartAndEnd() = super.statusBarLayerPositionAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
super.visibleLayersShownMoreThanOneConsecutiveEntry()
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
- super.visibleWindowsShownMoreThanOneConsecutiveEntry()
-
companion object {
@Parameterized.Parameters(name = "{0}")
@JvmStatic
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java
index e6711ac..8b025cd 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java
@@ -16,6 +16,8 @@
package com.android.wm.shell.bubbles;
+import static com.android.wm.shell.bubbles.Bubble.KEY_APP_BUBBLE;
+
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
@@ -32,6 +34,7 @@
import android.app.Notification;
import android.app.PendingIntent;
+import android.content.Intent;
import android.content.LocusId;
import android.graphics.drawable.Icon;
import android.os.Bundle;
@@ -94,6 +97,7 @@
private Bubble mBubbleInterruptive;
private Bubble mBubbleDismissed;
private Bubble mBubbleLocusId;
+ private Bubble mAppBubble;
private BubbleData mBubbleData;
private TestableBubblePositioner mPositioner;
@@ -178,6 +182,11 @@
mBubbleMetadataFlagListener,
mPendingIntentCanceledListener,
mMainExecutor);
+
+ Intent appBubbleIntent = new Intent(mContext, BubblesTestActivity.class);
+ appBubbleIntent.setPackage(mContext.getPackageName());
+ mAppBubble = new Bubble(appBubbleIntent, new UserHandle(1), mMainExecutor);
+
mPositioner = new TestableBubblePositioner(mContext,
mock(WindowManager.class));
mBubbleData = new BubbleData(getContext(), mBubbleLogger, mPositioner,
@@ -1089,6 +1098,18 @@
assertOverflowChangedTo(ImmutableList.of());
}
+ @Test
+ public void test_removeAppBubble_skipsOverflow() {
+ mBubbleData.notificationEntryUpdated(mAppBubble, true /* suppressFlyout*/,
+ false /* showInShade */);
+ assertThat(mBubbleData.getBubbleInStackWithKey(KEY_APP_BUBBLE)).isEqualTo(mAppBubble);
+
+ mBubbleData.dismissBubbleWithKey(KEY_APP_BUBBLE, Bubbles.DISMISS_USER_GESTURE);
+
+ assertThat(mBubbleData.getOverflowBubbleWithKey(KEY_APP_BUBBLE)).isNull();
+ assertThat(mBubbleData.getBubbleInStackWithKey(KEY_APP_BUBBLE)).isNull();
+ }
+
private void verifyUpdateReceived() {
verify(mListener).applyUpdate(mUpdateCaptor.capture());
reset(mListener);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsAlgorithmTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsAlgorithmTest.java
index 262e429..298d0a6 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsAlgorithmTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsAlgorithmTest.java
@@ -64,7 +64,7 @@
initializeMockResources();
mPipBoundsState = new PipBoundsState(mContext);
mPipBoundsAlgorithm = new PipBoundsAlgorithm(mContext, mPipBoundsState,
- new PipSnapAlgorithm(), new PipKeepClearAlgorithm() {});
+ new PipSnapAlgorithm(), new PipKeepClearAlgorithmInterface() {});
mPipBoundsState.setDisplayLayout(
new DisplayLayout(mDefaultDisplayInfo, mContext.getResources(), true, true));
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
index 9088077..17e7d74 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
@@ -98,7 +98,7 @@
mPipBoundsState = new PipBoundsState(mContext);
mPipTransitionState = new PipTransitionState();
mPipBoundsAlgorithm = new PipBoundsAlgorithm(mContext, mPipBoundsState,
- new PipSnapAlgorithm(), new PipKeepClearAlgorithm() {});
+ new PipSnapAlgorithm(), new PipKeepClearAlgorithmInterface() {});
mMainExecutor = new TestShellExecutor();
mPipTaskOrganizer = new PipTaskOrganizer(mContext,
mMockSyncTransactionQueue, mPipTransitionState, mPipBoundsState,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipResizeGestureHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipResizeGestureHandlerTest.java
index 3bd2ae7..c1993b2 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipResizeGestureHandlerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipResizeGestureHandlerTest.java
@@ -37,7 +37,7 @@
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.pip.PipBoundsAlgorithm;
import com.android.wm.shell.pip.PipBoundsState;
-import com.android.wm.shell.pip.PipKeepClearAlgorithm;
+import com.android.wm.shell.pip.PipKeepClearAlgorithmInterface;
import com.android.wm.shell.pip.PipSnapAlgorithm;
import com.android.wm.shell.pip.PipTaskOrganizer;
import com.android.wm.shell.pip.PipTransitionController;
@@ -90,8 +90,8 @@
MockitoAnnotations.initMocks(this);
mPipBoundsState = new PipBoundsState(mContext);
final PipSnapAlgorithm pipSnapAlgorithm = new PipSnapAlgorithm();
- final PipKeepClearAlgorithm pipKeepClearAlgorithm =
- new PipKeepClearAlgorithm() {};
+ final PipKeepClearAlgorithmInterface pipKeepClearAlgorithm =
+ new PipKeepClearAlgorithmInterface() {};
final PipBoundsAlgorithm pipBoundsAlgorithm = new PipBoundsAlgorithm(mContext,
mPipBoundsState, pipSnapAlgorithm, pipKeepClearAlgorithm);
final PipMotionHelper motionHelper = new PipMotionHelper(mContext, mPipBoundsState,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTouchHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTouchHandlerTest.java
index 474d6aa..8ad2932 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTouchHandlerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTouchHandlerTest.java
@@ -34,7 +34,7 @@
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.pip.PipBoundsAlgorithm;
import com.android.wm.shell.pip.PipBoundsState;
-import com.android.wm.shell.pip.PipKeepClearAlgorithm;
+import com.android.wm.shell.pip.PipKeepClearAlgorithmInterface;
import com.android.wm.shell.pip.PipSnapAlgorithm;
import com.android.wm.shell.pip.PipTaskOrganizer;
import com.android.wm.shell.pip.PipTransitionController;
@@ -106,7 +106,7 @@
mPipBoundsState = new PipBoundsState(mContext);
mPipSnapAlgorithm = new PipSnapAlgorithm();
mPipBoundsAlgorithm = new PipBoundsAlgorithm(mContext, mPipBoundsState, mPipSnapAlgorithm,
- new PipKeepClearAlgorithm() {});
+ new PipKeepClearAlgorithmInterface() {});
PipMotionHelper pipMotionHelper = new PipMotionHelper(mContext, mPipBoundsState,
mPipTaskOrganizer, mPhonePipMenuController, mPipSnapAlgorithm,
mMockPipTransitionController, mFloatingContentCoordinator);
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 59e4b7a..aeead5e 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -78,6 +78,7 @@
"external/skia/src/utils",
"external/skia/src/gpu",
"external/skia/src/shaders",
+ "external/skia/modules/skottie",
],
},
host: {
@@ -214,6 +215,15 @@
path: "apex/java",
}
+java_api_contribution {
+ name: "framework-graphics-public-stubs",
+ api_surface: "public",
+ api_file: "api/current.txt",
+ visibility: [
+ "//build/orchestrator/apis",
+ ],
+}
+
// ------------------------
// APEX
// ------------------------
@@ -375,6 +385,7 @@
"external/skia/src/effects",
"external/skia/src/image",
"external/skia/src/images",
+ "external/skia/modules/skottie",
],
shared_libs: [
@@ -402,6 +413,7 @@
"jni/BitmapRegionDecoder.cpp",
"jni/GIFMovie.cpp",
"jni/GraphicsStatsService.cpp",
+ "jni/LottieDrawable.cpp",
"jni/Movie.cpp",
"jni/MovieImpl.cpp",
"jni/pdf/PdfDocument.cpp",
@@ -509,6 +521,7 @@
"hwui/BlurDrawLooper.cpp",
"hwui/Canvas.cpp",
"hwui/ImageDecoder.cpp",
+ "hwui/LottieDrawable.cpp",
"hwui/MinikinSkia.cpp",
"hwui/MinikinUtils.cpp",
"hwui/PaintImpl.cpp",
diff --git a/libs/hwui/MemoryPolicy.h b/libs/hwui/MemoryPolicy.h
index 41ced8c..2f0f7f5 100644
--- a/libs/hwui/MemoryPolicy.h
+++ b/libs/hwui/MemoryPolicy.h
@@ -53,8 +53,8 @@
// Whether or not to only purge scratch resources when triggering UI Hidden or background
// collection
bool purgeScratchOnly = true;
- // EXPERIMENTAL: Whether or not to trigger releasing GPU context when all contexts are stopped
- bool releaseContextOnStoppedOnly = false;
+ // Whether or not to trigger releasing GPU context when all contexts are stopped
+ bool releaseContextOnStoppedOnly = true;
};
const MemoryPolicy& loadMemoryPolicy();
diff --git a/libs/hwui/Readback.cpp b/libs/hwui/Readback.cpp
index 8dcd6db..045de35 100644
--- a/libs/hwui/Readback.cpp
+++ b/libs/hwui/Readback.cpp
@@ -28,6 +28,7 @@
#include <SkRefCnt.h>
#include <SkSamplingOptions.h>
#include <SkSurface.h>
+#include "include/gpu/GpuTypes.h" // from Skia
#include <gui/TraceUtils.h>
#include <private/android/AHardwareBufferHelpers.h>
#include <shaders/shaders.h>
@@ -170,14 +171,15 @@
SkBitmap skBitmap = request->getDestinationBitmap(srcRect.width(), srcRect.height());
SkBitmap* bitmap = &skBitmap;
sk_sp<SkSurface> tmpSurface =
- SkSurface::MakeRenderTarget(mRenderThread.getGrContext(), SkBudgeted::kYes,
+ SkSurface::MakeRenderTarget(mRenderThread.getGrContext(), skgpu::Budgeted::kYes,
bitmap->info(), 0, kTopLeft_GrSurfaceOrigin, nullptr);
// if we can't generate a GPU surface that matches the destination bitmap (e.g. 565) then we
// attempt to do the intermediate rendering step in 8888
if (!tmpSurface.get()) {
SkImageInfo tmpInfo = bitmap->info().makeColorType(SkColorType::kN32_SkColorType);
- tmpSurface = SkSurface::MakeRenderTarget(mRenderThread.getGrContext(), SkBudgeted::kYes,
+ tmpSurface = SkSurface::MakeRenderTarget(mRenderThread.getGrContext(),
+ skgpu::Budgeted::kYes,
tmpInfo, 0, kTopLeft_GrSurfaceOrigin, nullptr);
if (!tmpSurface.get()) {
ALOGW("Unable to generate GPU buffer in a format compatible with the provided bitmap");
@@ -345,14 +347,17 @@
* software buffer.
*/
sk_sp<SkSurface> tmpSurface = SkSurface::MakeRenderTarget(mRenderThread.getGrContext(),
- SkBudgeted::kYes, bitmap->info(), 0,
+ skgpu::Budgeted::kYes,
+ bitmap->info(),
+ 0,
kTopLeft_GrSurfaceOrigin, nullptr);
// if we can't generate a GPU surface that matches the destination bitmap (e.g. 565) then we
// attempt to do the intermediate rendering step in 8888
if (!tmpSurface.get()) {
SkImageInfo tmpInfo = bitmap->info().makeColorType(SkColorType::kN32_SkColorType);
- tmpSurface = SkSurface::MakeRenderTarget(mRenderThread.getGrContext(), SkBudgeted::kYes,
+ tmpSurface = SkSurface::MakeRenderTarget(mRenderThread.getGrContext(),
+ skgpu::Budgeted::kYes,
tmpInfo, 0, kTopLeft_GrSurfaceOrigin, nullptr);
if (!tmpSurface.get()) {
ALOGW("Unable to generate GPU buffer in a format compatible with the provided bitmap");
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 5b6fff1..e1030b0 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -44,6 +44,7 @@
#include "SkTextBlob.h"
#include "SkVertices.h"
#include "VectorDrawable.h"
+#include "include/gpu/GpuTypes.h" // from Skia
#include "pipeline/skia/AnimatedDrawables.h"
#include "pipeline/skia/FunctorDrawable.h"
@@ -570,7 +571,7 @@
GrRecordingContext* directContext = c->recordingContext();
mLayerImageInfo =
c->imageInfo().makeWH(deviceBounds.width(), deviceBounds.height());
- mLayerSurface = SkSurface::MakeRenderTarget(directContext, SkBudgeted::kYes,
+ mLayerSurface = SkSurface::MakeRenderTarget(directContext, skgpu::Budgeted::kYes,
mLayerImageInfo, 0,
kTopLeft_GrSurfaceOrigin, nullptr);
}
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index 2539694..b7d4dc9 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -16,11 +16,13 @@
#pragma once
-#include "CanvasTransform.h"
-#include "hwui/Bitmap.h"
-#include "utils/Macros.h"
-#include "utils/TypeLogic.h"
+#include <SkRuntimeEffect.h>
+#include <log/log.h>
+#include <cstdlib>
+#include <vector>
+
+#include "CanvasTransform.h"
#include "SkCanvas.h"
#include "SkCanvasVirtualEnforcer.h"
#include "SkDrawable.h"
@@ -28,11 +30,11 @@
#include "SkPaint.h"
#include "SkPath.h"
#include "SkRect.h"
-
+#include "hwui/Bitmap.h"
#include "pipeline/skia/AnimatedDrawables.h"
-
-#include <SkRuntimeEffect.h>
-#include <vector>
+#include "utils/AutoMalloc.h"
+#include "utils/Macros.h"
+#include "utils/TypeLogic.h"
enum class SkBlendMode;
class SkRRect;
@@ -145,7 +147,7 @@
template <typename Fn, typename... Args>
void map(const Fn[], Args...) const;
- SkAutoTMalloc<uint8_t> fBytes;
+ AutoTMalloc<uint8_t> fBytes;
size_t fUsed = 0;
size_t fReserved = 0;
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index d83d78f..af8bd26 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -16,23 +16,12 @@
#include "SkiaCanvas.h"
-#include "CanvasProperty.h"
-#include "NinePatchUtils.h"
-#include "SkBlendMode.h"
-#include "VectorDrawable.h"
-#include "hwui/Bitmap.h"
-#include "hwui/MinikinUtils.h"
-#include "hwui/PaintFilter.h"
-#include "pipeline/skia/AnimatedDrawables.h"
-#include "pipeline/skia/HolePunch.h"
-
#include <SkAndroidFrameworkUtils.h>
#include <SkAnimatedImage.h>
#include <SkBitmap.h>
#include <SkCanvasPriv.h>
#include <SkCanvasStateUtils.h>
#include <SkColorFilter.h>
-#include <SkDeque.h>
#include <SkDrawable.h>
#include <SkFont.h>
#include <SkGraphics.h>
@@ -41,8 +30,8 @@
#include <SkMatrix.h>
#include <SkPaint.h>
#include <SkPicture.h>
-#include <SkRSXform.h>
#include <SkRRect.h>
+#include <SkRSXform.h>
#include <SkRect.h>
#include <SkRefCnt.h>
#include <SkShader.h>
@@ -54,6 +43,16 @@
#include <optional>
#include <utility>
+#include "CanvasProperty.h"
+#include "NinePatchUtils.h"
+#include "SkBlendMode.h"
+#include "VectorDrawable.h"
+#include "hwui/Bitmap.h"
+#include "hwui/MinikinUtils.h"
+#include "hwui/PaintFilter.h"
+#include "pipeline/skia/AnimatedDrawables.h"
+#include "pipeline/skia/HolePunch.h"
+
namespace android {
using uirenderer::PaintUtils;
@@ -176,7 +175,7 @@
// operation. It does this by explicitly saving off the clip & matrix state
// when requested and playing it back after the SkCanvas::restore.
void SkiaCanvas::restore() {
- const auto* rec = this->currentSaveRec();
+ const SaveRec* rec = this->currentSaveRec();
if (!rec) {
// Fast path - no record for this frame.
mCanvas->restore();
@@ -245,7 +244,9 @@
}
const SkiaCanvas::SaveRec* SkiaCanvas::currentSaveRec() const {
- const SaveRec* rec = mSaveStack ? static_cast<const SaveRec*>(mSaveStack->back()) : nullptr;
+ const SaveRec* rec = (mSaveStack && !mSaveStack->empty())
+ ? static_cast<const SaveRec*>(&mSaveStack->back())
+ : nullptr;
int currentSaveCount = mCanvas->getSaveCount();
SkASSERT(!rec || currentSaveCount >= rec->saveCount);
@@ -277,13 +278,12 @@
}
if (!mSaveStack) {
- mSaveStack.reset(new SkDeque(sizeof(struct SaveRec), 8));
+ mSaveStack.reset(new std::deque<SaveRec>());
}
- SaveRec* rec = static_cast<SaveRec*>(mSaveStack->push_back());
- rec->saveCount = mCanvas->getSaveCount();
- rec->saveFlags = flags;
- rec->clipIndex = mClipStack.size();
+ mSaveStack->emplace_back(mCanvas->getSaveCount(), // saveCount
+ flags, // saveFlags
+ mClipStack.size()); // clipIndex
}
template <typename T>
@@ -314,7 +314,7 @@
// If the current/post-restore save rec is also persisting clips, we
// leave them on the stack to be reapplied part of the next restore().
// Otherwise we're done and just pop them.
- const auto* rec = this->currentSaveRec();
+ const SaveRec* rec = this->currentSaveRec();
if (!rec || (rec->saveFlags & SaveFlags::Clip)) {
mClipStack.erase(begin, end);
}
@@ -736,6 +736,10 @@
return imgDrawable->drawStaging(mCanvas);
}
+void SkiaCanvas::drawLottie(LottieDrawable* lottieDrawable) {
+ lottieDrawable->drawStaging(mCanvas);
+}
+
void SkiaCanvas::drawVectorDrawable(VectorDrawableRoot* vectorDrawable) {
vectorDrawable->drawStaging(this);
}
diff --git a/libs/hwui/SkiaCanvas.h b/libs/hwui/SkiaCanvas.h
index 31e3b4c..1524dff 100644
--- a/libs/hwui/SkiaCanvas.h
+++ b/libs/hwui/SkiaCanvas.h
@@ -19,20 +19,19 @@
#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
#include "DeferredLayerUpdater.h"
#endif
-#include "RenderNode.h"
-#include "VectorDrawable.h"
-#include "hwui/Canvas.h"
-#include "hwui/Paint.h"
-#include "hwui/BlurDrawLooper.h"
-
#include <SkCanvas.h>
-#include <SkDeque.h>
-#include "pipeline/skia/AnimatedDrawables.h"
-#include "src/core/SkArenaAlloc.h"
#include <cassert>
+#include <deque>
#include <optional>
+#include "RenderNode.h"
+#include "VectorDrawable.h"
+#include "hwui/BlurDrawLooper.h"
+#include "hwui/Canvas.h"
+#include "hwui/Paint.h"
+#include "pipeline/skia/AnimatedDrawables.h"
+
enum class SkBlendMode;
class SkRRect;
@@ -145,6 +144,7 @@
float dstTop, float dstRight, float dstBottom,
const Paint* paint) override;
virtual double drawAnimatedImage(AnimatedImageDrawable* imgDrawable) override;
+ virtual void drawLottie(LottieDrawable* lottieDrawable) override;
virtual void drawVectorDrawable(VectorDrawableRoot* vectorDrawable) override;
@@ -211,6 +211,9 @@
int saveCount;
SaveFlags::Flags saveFlags;
size_t clipIndex;
+
+ SaveRec(int saveCount, SaveFlags::Flags saveFlags, size_t clipIndex)
+ : saveCount(saveCount), saveFlags(saveFlags), clipIndex(clipIndex) {}
};
const SaveRec* currentSaveRec() const;
@@ -224,11 +227,11 @@
class Clip;
- std::unique_ptr<SkCanvas> mCanvasOwned; // might own a canvas we allocated
- SkCanvas* mCanvas; // we do NOT own this canvas, it must survive us
- // unless it is the same as mCanvasOwned.get()
- std::unique_ptr<SkDeque> mSaveStack; // lazily allocated, tracks partial saves.
- std::vector<Clip> mClipStack; // tracks persistent clips.
+ std::unique_ptr<SkCanvas> mCanvasOwned; // Might own a canvas we allocated.
+ SkCanvas* mCanvas; // We do NOT own this canvas, it must survive us
+ // unless it is the same as mCanvasOwned.get().
+ std::unique_ptr<std::deque<SaveRec>> mSaveStack; // Lazily allocated, tracks partial saves.
+ std::vector<Clip> mClipStack; // Tracks persistent clips.
sk_sp<PaintFilter> mPaintFilter;
};
diff --git a/libs/hwui/apex/jni_runtime.cpp b/libs/hwui/apex/jni_runtime.cpp
index f57d80c..b1aa1947 100644
--- a/libs/hwui/apex/jni_runtime.cpp
+++ b/libs/hwui/apex/jni_runtime.cpp
@@ -37,6 +37,7 @@
extern int register_android_graphics_Graphics(JNIEnv* env);
extern int register_android_graphics_ImageDecoder(JNIEnv*);
extern int register_android_graphics_drawable_AnimatedImageDrawable(JNIEnv*);
+extern int register_android_graphics_drawable_LottieDrawable(JNIEnv*);
extern int register_android_graphics_Interpolator(JNIEnv* env);
extern int register_android_graphics_MaskFilter(JNIEnv* env);
extern int register_android_graphics_Movie(JNIEnv* env);
@@ -117,6 +118,7 @@
REG_JNI(register_android_graphics_HardwareRendererObserver),
REG_JNI(register_android_graphics_ImageDecoder),
REG_JNI(register_android_graphics_drawable_AnimatedImageDrawable),
+ REG_JNI(register_android_graphics_drawable_LottieDrawable),
REG_JNI(register_android_graphics_Interpolator),
REG_JNI(register_android_graphics_MaskFilter),
REG_JNI(register_android_graphics_Matrix),
diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h
index 2a20191..07e2fe2 100644
--- a/libs/hwui/hwui/Canvas.h
+++ b/libs/hwui/hwui/Canvas.h
@@ -60,6 +60,7 @@
typedef std::function<void(uint16_t* text, float* positions)> ReadGlyphFunc;
class AnimatedImageDrawable;
+class LottieDrawable;
class Bitmap;
class Paint;
struct Typeface;
@@ -242,6 +243,7 @@
const Paint* paint) = 0;
virtual double drawAnimatedImage(AnimatedImageDrawable* imgDrawable) = 0;
+ virtual void drawLottie(LottieDrawable* lottieDrawable) = 0;
virtual void drawPicture(const SkPicture& picture) = 0;
/**
diff --git a/libs/hwui/hwui/LottieDrawable.cpp b/libs/hwui/hwui/LottieDrawable.cpp
new file mode 100644
index 0000000..92dc51e
--- /dev/null
+++ b/libs/hwui/hwui/LottieDrawable.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "LottieDrawable.h"
+
+#include <SkTime.h>
+#include <log/log.h>
+#include <pipeline/skia/SkiaUtils.h>
+
+namespace android {
+
+sk_sp<LottieDrawable> LottieDrawable::Make(sk_sp<skottie::Animation> animation, size_t bytesUsed) {
+ if (animation) {
+ return sk_sp<LottieDrawable>(new LottieDrawable(std::move(animation), bytesUsed));
+ }
+ return nullptr;
+}
+LottieDrawable::LottieDrawable(sk_sp<skottie::Animation> animation, size_t bytesUsed)
+ : mAnimation(std::move(animation)), mBytesUsed(bytesUsed) {}
+
+bool LottieDrawable::start() {
+ if (mRunning) {
+ return false;
+ }
+
+ mRunning = true;
+ return true;
+}
+
+bool LottieDrawable::stop() {
+ bool wasRunning = mRunning;
+ mRunning = false;
+ return wasRunning;
+}
+
+bool LottieDrawable::isRunning() {
+ return mRunning;
+}
+
+// TODO: Check to see if drawable is actually dirty
+bool LottieDrawable::isDirty() {
+ return true;
+}
+
+void LottieDrawable::onDraw(SkCanvas* canvas) {
+ if (mRunning) {
+ const nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
+
+ nsecs_t t = 0;
+ if (mStartTime == 0) {
+ mStartTime = currentTime;
+ } else {
+ t = currentTime - mStartTime;
+ }
+ double seekTime = std::fmod((double)t * 1e-9, mAnimation->duration());
+ mAnimation->seekFrameTime(seekTime);
+ mAnimation->render(canvas);
+ }
+}
+
+void LottieDrawable::drawStaging(SkCanvas* canvas) {
+ onDraw(canvas);
+}
+
+SkRect LottieDrawable::onGetBounds() {
+ // We do not actually know the bounds, so give a conservative answer.
+ return SkRectMakeLargest();
+}
+
+} // namespace android
diff --git a/libs/hwui/hwui/LottieDrawable.h b/libs/hwui/hwui/LottieDrawable.h
new file mode 100644
index 0000000..9cc34bf
--- /dev/null
+++ b/libs/hwui/hwui/LottieDrawable.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <SkDrawable.h>
+#include <Skottie.h>
+#include <utils/Timers.h>
+
+class SkCanvas;
+
+namespace android {
+
+/**
+ * Native component of android.graphics.drawable.LottieDrawable.java.
+ * This class can be drawn into Canvas.h and maintains the state needed to drive
+ * the animation from the RenderThread.
+ */
+class LottieDrawable : public SkDrawable {
+public:
+ static sk_sp<LottieDrawable> Make(sk_sp<skottie::Animation> animation, size_t bytes);
+
+ // Draw to software canvas
+ void drawStaging(SkCanvas* canvas);
+
+ // Returns true if the animation was started; false otherwise (e.g. it was
+ // already running)
+ bool start();
+ // Returns true if the animation was stopped; false otherwise (e.g. it was
+ // already stopped)
+ bool stop();
+ bool isRunning();
+
+ // TODO: Is dirty should take in a time til next frame to determine if it is dirty
+ bool isDirty();
+
+ SkRect onGetBounds() override;
+
+ size_t byteSize() const { return sizeof(*this) + mBytesUsed; }
+
+protected:
+ void onDraw(SkCanvas* canvas) override;
+
+private:
+ LottieDrawable(sk_sp<skottie::Animation> animation, size_t bytes_used);
+
+ sk_sp<skottie::Animation> mAnimation;
+ bool mRunning = false;
+ // The start time for the drawable itself.
+ nsecs_t mStartTime = 0;
+ const size_t mBytesUsed = 0;
+};
+
+} // namespace android
diff --git a/libs/hwui/jni/LottieDrawable.cpp b/libs/hwui/jni/LottieDrawable.cpp
new file mode 100644
index 0000000..fb6eede
--- /dev/null
+++ b/libs/hwui/jni/LottieDrawable.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <SkRect.h>
+#include <Skottie.h>
+#include <hwui/Canvas.h>
+#include <hwui/LottieDrawable.h>
+
+#include "GraphicsJNI.h"
+#include "Utils.h"
+
+using namespace android;
+
+static jclass gLottieDrawableClass;
+
+static jlong LottieDrawable_nCreate(JNIEnv* env, jobject, jstring jjson) {
+ const ScopedUtfChars cstr(env, jjson);
+ // TODO(b/259267150) provide more accurate byteSize
+ size_t bytes = strlen(cstr.c_str());
+ auto animation = skottie::Animation::Builder().make(cstr.c_str(), bytes);
+ sk_sp<LottieDrawable> drawable(LottieDrawable::Make(std::move(animation), bytes));
+ if (!drawable) {
+ return 0;
+ }
+ return reinterpret_cast<jlong>(drawable.release());
+}
+
+static void LottieDrawable_destruct(LottieDrawable* drawable) {
+ SkSafeUnref(drawable);
+}
+
+static jlong LottieDrawable_nGetNativeFinalizer(JNIEnv* /*env*/, jobject /*clazz*/) {
+ return static_cast<jlong>(reinterpret_cast<uintptr_t>(&LottieDrawable_destruct));
+}
+
+static void LottieDrawable_nDraw(JNIEnv* env, jobject /*clazz*/, jlong nativePtr, jlong canvasPtr) {
+ auto* drawable = reinterpret_cast<LottieDrawable*>(nativePtr);
+ auto* canvas = reinterpret_cast<Canvas*>(canvasPtr);
+ canvas->drawLottie(drawable);
+}
+
+static jboolean LottieDrawable_nIsRunning(JNIEnv* env, jobject /*clazz*/, jlong nativePtr) {
+ auto* drawable = reinterpret_cast<LottieDrawable*>(nativePtr);
+ return drawable->isRunning();
+}
+
+static jboolean LottieDrawable_nStart(JNIEnv* env, jobject /*clazz*/, jlong nativePtr) {
+ auto* drawable = reinterpret_cast<LottieDrawable*>(nativePtr);
+ return drawable->start();
+}
+
+static jboolean LottieDrawable_nStop(JNIEnv* env, jobject /*clazz*/, jlong nativePtr) {
+ auto* drawable = reinterpret_cast<LottieDrawable*>(nativePtr);
+ return drawable->stop();
+}
+
+static jlong LottieDrawable_nNativeByteSize(JNIEnv* env, jobject /*clazz*/, jlong nativePtr) {
+ auto* drawable = reinterpret_cast<LottieDrawable*>(nativePtr);
+ return drawable->byteSize();
+}
+
+static const JNINativeMethod gLottieDrawableMethods[] = {
+ {"nCreate", "(Ljava/lang/String;)J", (void*)LottieDrawable_nCreate},
+ {"nNativeByteSize", "(J)J", (void*)LottieDrawable_nNativeByteSize},
+ {"nGetNativeFinalizer", "()J", (void*)LottieDrawable_nGetNativeFinalizer},
+ {"nDraw", "(JJ)V", (void*)LottieDrawable_nDraw},
+ {"nIsRunning", "(J)Z", (void*)LottieDrawable_nIsRunning},
+ {"nStart", "(J)Z", (void*)LottieDrawable_nStart},
+ {"nStop", "(J)Z", (void*)LottieDrawable_nStop},
+};
+
+int register_android_graphics_drawable_LottieDrawable(JNIEnv* env) {
+ gLottieDrawableClass = reinterpret_cast<jclass>(
+ env->NewGlobalRef(FindClassOrDie(env, "android/graphics/drawable/LottieDrawable")));
+
+ return android::RegisterMethodsOrDie(env, "android/graphics/drawable/LottieDrawable",
+ gLottieDrawableMethods, NELEM(gLottieDrawableMethods));
+}
diff --git a/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp b/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp
index dc72aea..a4960ea 100644
--- a/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp
+++ b/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp
@@ -24,6 +24,7 @@
#include "SkClipStack.h"
#include "SkRect.h"
#include "SkM44.h"
+#include "include/gpu/GpuTypes.h" // from Skia
#include "utils/GLUtils.h"
namespace android {
@@ -92,7 +93,7 @@
SkImageInfo surfaceInfo =
canvas->imageInfo().makeWH(clipBounds.width(), clipBounds.height());
tmpSurface =
- SkSurface::MakeRenderTarget(directContext, SkBudgeted::kYes, surfaceInfo);
+ SkSurface::MakeRenderTarget(directContext, skgpu::Budgeted::kYes, surfaceInfo);
tmpSurface->getCanvas()->clear(SK_ColorTRANSPARENT);
GrGLFramebufferInfo fboInfo;
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
index fcfc4f8..f0dc5eb 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
@@ -146,6 +146,16 @@
}
}
+ for (auto& lottie : mLotties) {
+ // If any animated image in the display list needs updated, then damage the node.
+ if (lottie->isDirty()) {
+ isDirty = true;
+ }
+ if (lottie->isRunning()) {
+ info.out.hasAnimations = true;
+ }
+ }
+
for (auto& [vectorDrawable, cachedMatrix] : mVectorDrawables) {
// If any vector drawable in the display list needs update, damage the node.
if (vectorDrawable->isDirty()) {
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.h b/libs/hwui/pipeline/skia/SkiaDisplayList.h
index 2a67734..39217fc 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.h
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.h
@@ -22,6 +22,7 @@
#include "RenderNodeDrawable.h"
#include "TreeInfo.h"
#include "hwui/AnimatedImageDrawable.h"
+#include "hwui/LottieDrawable.h"
#include "utils/LinearAllocator.h"
#include "utils/Pair.h"
@@ -186,6 +187,8 @@
return mHasHolePunches;
}
+ // TODO(b/257304231): create common base class for Lotties and AnimatedImages
+ std::vector<LottieDrawable*> mLotties;
std::vector<AnimatedImageDrawable*> mAnimatedImages;
DisplayListData mDisplayList;
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 1a336c5..3692f09 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -36,6 +36,7 @@
#include <SkStream.h>
#include <SkString.h>
#include <SkTypeface.h>
+#include "include/gpu/GpuTypes.h" // from Skia
#include <android-base/properties.h>
#include <unistd.h>
@@ -187,7 +188,7 @@
SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
SkASSERT(mRenderThread.getGrContext() != nullptr);
node->setLayerSurface(SkSurface::MakeRenderTarget(mRenderThread.getGrContext(),
- SkBudgeted::kYes, info, 0,
+ skgpu::Budgeted::kYes, info, 0,
this->getSurfaceOrigin(), &props));
if (node->getLayerSurface()) {
// update the transform in window of the layer to reset its origin wrt light source
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index 1f87865..db449d6 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -188,6 +188,11 @@
#endif
}
+void SkiaRecordingCanvas::drawLottie(LottieDrawable* lottie) {
+ drawDrawable(lottie);
+ mDisplayList->mLotties.push_back(lottie);
+}
+
void SkiaRecordingCanvas::drawVectorDrawable(VectorDrawableRoot* tree) {
mRecorder.drawVectorDrawable(tree);
SkMatrix mat;
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
index 7844e2c..c823d8d 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
@@ -78,6 +78,7 @@
uirenderer::CanvasPropertyPaint* paint) override;
virtual void drawRipple(const RippleDrawableParams& params) override;
+ virtual void drawLottie(LottieDrawable* lottieDrawable) override;
virtual void drawVectorDrawable(VectorDrawableRoot* vectorDrawable) override;
virtual void enableZ(bool enableZ) override;
diff --git a/libs/hwui/pipeline/skia/StretchMask.cpp b/libs/hwui/pipeline/skia/StretchMask.cpp
index b169c92..cad3703 100644
--- a/libs/hwui/pipeline/skia/StretchMask.cpp
+++ b/libs/hwui/pipeline/skia/StretchMask.cpp
@@ -18,6 +18,8 @@
#include "SkBlendMode.h"
#include "SkCanvas.h"
#include "SkSurface.h"
+#include "include/gpu/GpuTypes.h" // from Skia
+
#include "TransformCanvas.h"
#include "SkiaDisplayList.h"
@@ -36,7 +38,7 @@
// not match.
mMaskSurface = SkSurface::MakeRenderTarget(
context,
- SkBudgeted::kYes,
+ skgpu::Budgeted::kYes,
SkImageInfo::Make(
width,
height,
diff --git a/libs/hwui/tests/unit/CacheManagerTests.cpp b/libs/hwui/tests/unit/CacheManagerTests.cpp
index 508e198..2b90bda 100644
--- a/libs/hwui/tests/unit/CacheManagerTests.cpp
+++ b/libs/hwui/tests/unit/CacheManagerTests.cpp
@@ -21,6 +21,7 @@
#include "tests/common/TestUtils.h"
#include <SkImagePriv.h>
+#include "include/gpu/GpuTypes.h" // from Skia
using namespace android;
using namespace android::uirenderer;
@@ -45,7 +46,8 @@
while (getCacheUsage(grContext) <= renderThread.cacheManager().getBackgroundCacheSize()) {
SkImageInfo info = SkImageInfo::MakeA8(width, height);
- sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(grContext, SkBudgeted::kYes, info);
+ sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(grContext, skgpu::Budgeted::kYes,
+ info);
surface->getCanvas()->drawColor(SK_AlphaTRANSPARENT);
grContext->flushAndSubmit();
diff --git a/libs/hwui/utils/AutoMalloc.h b/libs/hwui/utils/AutoMalloc.h
new file mode 100644
index 0000000..05f5e9f
--- /dev/null
+++ b/libs/hwui/utils/AutoMalloc.h
@@ -0,0 +1,94 @@
+/**
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cstdlib>
+#include <memory>
+#include <type_traits>
+
+namespace android {
+namespace uirenderer {
+
+/** Manages an array of T elements, freeing the array in the destructor.
+ * Does NOT call any constructors/destructors on T (T must be POD).
+ */
+template <typename T,
+ typename = std::enable_if_t<std::is_trivially_default_constructible<T>::value &&
+ std::is_trivially_destructible<T>::value>>
+class AutoTMalloc {
+public:
+ /** Takes ownership of the ptr. The ptr must be a value which can be passed to std::free. */
+ explicit AutoTMalloc(T* ptr = nullptr) : fPtr(ptr) {}
+
+ /** Allocates space for 'count' Ts. */
+ explicit AutoTMalloc(size_t count) : fPtr(mallocIfCountThrowOnFail(count)) {}
+
+ AutoTMalloc(AutoTMalloc&&) = default;
+ AutoTMalloc& operator=(AutoTMalloc&&) = default;
+
+ /** Resize the memory area pointed to by the current ptr preserving contents. */
+ void realloc(size_t count) { fPtr.reset(reallocIfCountThrowOnFail(count)); }
+
+ /** Resize the memory area pointed to by the current ptr without preserving contents. */
+ T* reset(size_t count = 0) {
+ fPtr.reset(mallocIfCountThrowOnFail(count));
+ return this->get();
+ }
+
+ T* get() const { return fPtr.get(); }
+
+ operator T*() { return fPtr.get(); }
+
+ operator const T*() const { return fPtr.get(); }
+
+ T& operator[](int index) { return fPtr.get()[index]; }
+
+ const T& operator[](int index) const { return fPtr.get()[index]; }
+
+ /**
+ * Transfer ownership of the ptr to the caller, setting the internal
+ * pointer to NULL. Note that this differs from get(), which also returns
+ * the pointer, but it does not transfer ownership.
+ */
+ T* release() { return fPtr.release(); }
+
+private:
+ struct FreeDeleter {
+ void operator()(uint8_t* p) { std::free(p); }
+ };
+ std::unique_ptr<T, FreeDeleter> fPtr;
+
+ T* mallocIfCountThrowOnFail(size_t count) {
+ T* newPtr = nullptr;
+ if (count) {
+ newPtr = (T*)std::malloc(count * sizeof(T));
+ LOG_ALWAYS_FATAL_IF(!newPtr, "failed to malloc %zu bytes", count * sizeof(T));
+ }
+ return newPtr;
+ }
+ T* reallocIfCountThrowOnFail(size_t count) {
+ T* newPtr = nullptr;
+ if (count) {
+ newPtr = (T*)std::realloc(fPtr.release(), count * sizeof(T));
+ LOG_ALWAYS_FATAL_IF(!newPtr, "failed to realloc %zu bytes", count * sizeof(T));
+ }
+ return newPtr;
+ }
+};
+
+} // namespace uirenderer
+} // namespace android
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 4475aed..24c5b41 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -7022,6 +7022,10 @@
* Returns an array of {@link AudioDeviceInfo} objects corresponding to the audio devices
* currently connected to the system and meeting the criteria specified in the
* <code>flags</code> parameter.
+ * Notes that Android audio framework only support one device per device type. In that case,
+ * if there are multiple audio device with the same device type connected to the Android device,
+ * only the last reported device will be known by Android audio framework and returned by this
+ * API.
* @param flags A set of bitflags specifying the criteria to test.
* @see #GET_DEVICES_OUTPUTS
* @see #GET_DEVICES_INPUTS
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 273c7af..4323c73 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -708,12 +708,10 @@
* It's easier to create it here than in C++.
*/
try (ScopedParcelState attributionSourceState = attributionSource.asScopedParcelState()) {
- native_setup(new WeakReference<MediaPlayer>(this), attributionSourceState.getParcel());
+ native_setup(new WeakReference<>(this), attributionSourceState.getParcel(),
+ resolvePlaybackSessionId(context, sessionId));
}
-
- int effectiveSessionId = resolvePlaybackSessionId(context, sessionId);
- baseRegisterPlayer(effectiveSessionId);
- native_setAudioSessionId(effectiveSessionId);
+ baseRegisterPlayer(getAudioSessionId());
}
private Parcel createPlayerIIdParcel() {
@@ -1022,8 +1020,6 @@
final AudioAttributes aa = audioAttributes != null ? audioAttributes :
new AudioAttributes.Builder().build();
mp.setAudioAttributes(aa);
- mp.native_setAudioSessionId(audioSessionId);
-
mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
afd.close();
mp.prepare();
@@ -2521,7 +2517,7 @@
private static native final void native_init();
private native void native_setup(Object mediaplayerThis,
- @NonNull Parcel attributionSource);
+ @NonNull Parcel attributionSource, int audioSessionId);
private native final void native_finalize();
/**
diff --git a/media/java/android/media/RoutingSessionInfo.java b/media/java/android/media/RoutingSessionInfo.java
index 0982132..e1af909 100644
--- a/media/java/android/media/RoutingSessionInfo.java
+++ b/media/java/android/media/RoutingSessionInfo.java
@@ -23,7 +23,6 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
-import android.util.Log;
import com.android.internal.util.Preconditions;
@@ -117,6 +116,8 @@
mProviderId = src.readString();
mSelectedRoutes = ensureList(src.createStringArrayList());
+ Preconditions.checkArgument(!mSelectedRoutes.isEmpty());
+
mSelectableRoutes = ensureList(src.createStringArrayList());
mDeselectableRoutes = ensureList(src.createStringArrayList());
mTransferableRoutes = ensureList(src.createStringArrayList());
@@ -416,15 +417,21 @@
return result.toString();
}
+ /**
+ * Provides a new list with unique route IDs if {@link #mProviderId} is set, or the original IDs
+ * otherwise.
+ *
+ * @param routeIds list of route IDs to convert
+ * @return new list with unique IDs or original IDs
+ */
+
+ @NonNull
private List<String> convertToUniqueRouteIds(@NonNull List<String> routeIds) {
- if (routeIds == null) {
- Log.w(TAG, "routeIds is null. Returning an empty list");
- return Collections.emptyList();
- }
+ Objects.requireNonNull(routeIds, "RouteIds cannot be null.");
// mProviderId can be null if not set. Return the original list for this case.
if (TextUtils.isEmpty(mProviderId)) {
- return routeIds;
+ return new ArrayList<>(routeIds);
}
List<String> result = new ArrayList<>();
diff --git a/media/java/android/media/audiopolicy/AudioProductStrategy.java b/media/java/android/media/audiopolicy/AudioProductStrategy.java
index 98819a3..0198419 100644
--- a/media/java/android/media/audiopolicy/AudioProductStrategy.java
+++ b/media/java/android/media/audiopolicy/AudioProductStrategy.java
@@ -28,11 +28,11 @@
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.Preconditions;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
/**
* @hide
@@ -140,7 +140,7 @@
*/
public static int getLegacyStreamTypeForStrategyWithAudioAttributes(
@NonNull AudioAttributes audioAttributes) {
- Preconditions.checkNotNull(audioAttributes, "AudioAttributes must not be null");
+ Objects.requireNonNull(audioAttributes, "AudioAttributes must not be null");
for (final AudioProductStrategy productStrategy :
AudioProductStrategy.getAudioProductStrategies()) {
if (productStrategy.supportsAudioAttributes(audioAttributes)) {
@@ -160,6 +160,30 @@
return AudioSystem.STREAM_MUSIC;
}
+ /**
+ * @hide
+ * @param attributes the {@link AudioAttributes} to identify VolumeGroupId with
+ * @param fallbackOnDefault if set, allows to fallback on the default group (e.g. the group
+ * associated to {@link AudioManager#STREAM_MUSIC}).
+ * @return volume group id associated with the given {@link AudioAttributes} if found,
+ * default volume group id if fallbackOnDefault is set
+ * <p>By convention, the product strategy with default attributes will be associated to the
+ * default volume group (e.g. associated to {@link AudioManager#STREAM_MUSIC})
+ * or {@link AudioVolumeGroup#DEFAULT_VOLUME_GROUP} if not found.
+ */
+ public static int getVolumeGroupIdForAudioAttributes(
+ @NonNull AudioAttributes attributes, boolean fallbackOnDefault) {
+ Objects.requireNonNull(attributes, "attributes must not be null");
+ int volumeGroupId = getVolumeGroupIdForAudioAttributesInt(attributes);
+ if (volumeGroupId != AudioVolumeGroup.DEFAULT_VOLUME_GROUP) {
+ return volumeGroupId;
+ }
+ if (fallbackOnDefault) {
+ return getVolumeGroupIdForAudioAttributesInt(getDefaultAttributes());
+ }
+ return AudioVolumeGroup.DEFAULT_VOLUME_GROUP;
+ }
+
private static List<AudioProductStrategy> initializeAudioProductStrategies() {
ArrayList<AudioProductStrategy> apsList = new ArrayList<AudioProductStrategy>();
int status = native_list_audio_product_strategies(apsList);
@@ -190,8 +214,8 @@
*/
private AudioProductStrategy(@NonNull String name, int id,
@NonNull AudioAttributesGroup[] aag) {
- Preconditions.checkNotNull(name, "name must not be null");
- Preconditions.checkNotNull(aag, "AudioAttributesGroups must not be null");
+ Objects.requireNonNull(name, "name must not be null");
+ Objects.requireNonNull(aag, "AudioAttributesGroups must not be null");
mName = name;
mId = id;
mAudioAttributesGroups = aag;
@@ -241,7 +265,7 @@
*/
@TestApi
public int getLegacyStreamTypeForAudioAttributes(@NonNull AudioAttributes aa) {
- Preconditions.checkNotNull(aa, "AudioAttributes must not be null");
+ Objects.requireNonNull(aa, "AudioAttributes must not be null");
for (final AudioAttributesGroup aag : mAudioAttributesGroups) {
if (aag.supportsAttributes(aa)) {
return aag.getStreamType();
@@ -258,7 +282,7 @@
*/
@SystemApi
public boolean supportsAudioAttributes(@NonNull AudioAttributes aa) {
- Preconditions.checkNotNull(aa, "AudioAttributes must not be null");
+ Objects.requireNonNull(aa, "AudioAttributes must not be null");
for (final AudioAttributesGroup aag : mAudioAttributesGroups) {
if (aag.supportsAttributes(aa)) {
return true;
@@ -291,7 +315,7 @@
*/
@TestApi
public int getVolumeGroupIdForAudioAttributes(@NonNull AudioAttributes aa) {
- Preconditions.checkNotNull(aa, "AudioAttributes must not be null");
+ Objects.requireNonNull(aa, "AudioAttributes must not be null");
for (final AudioAttributesGroup aag : mAudioAttributesGroups) {
if (aag.supportsAttributes(aa)) {
return aag.getVolumeGroupId();
@@ -300,6 +324,17 @@
return AudioVolumeGroup.DEFAULT_VOLUME_GROUP;
}
+ private static int getVolumeGroupIdForAudioAttributesInt(@NonNull AudioAttributes attributes) {
+ Objects.requireNonNull(attributes, "attributes must not be null");
+ for (AudioProductStrategy productStrategy : getAudioProductStrategies()) {
+ int volumeGroupId = productStrategy.getVolumeGroupIdForAudioAttributes(attributes);
+ if (volumeGroupId != AudioVolumeGroup.DEFAULT_VOLUME_GROUP) {
+ return volumeGroupId;
+ }
+ }
+ return AudioVolumeGroup.DEFAULT_VOLUME_GROUP;
+ }
+
@Override
public int describeContents() {
return 0;
@@ -374,8 +409,8 @@
*/
private static boolean attributesMatches(@NonNull AudioAttributes refAttr,
@NonNull AudioAttributes attr) {
- Preconditions.checkNotNull(refAttr, "refAttr must not be null");
- Preconditions.checkNotNull(attr, "attr must not be null");
+ Objects.requireNonNull(refAttr, "reference AudioAttributes must not be null");
+ Objects.requireNonNull(attr, "requester's AudioAttributes must not be null");
String refFormattedTags = TextUtils.join(";", refAttr.getTags());
String cliFormattedTags = TextUtils.join(";", attr.getTags());
if (refAttr.equals(DEFAULT_ATTRIBUTES)) {
diff --git a/media/java/android/media/projection/MediaProjectionConfig.java b/media/java/android/media/projection/MediaProjectionConfig.java
index 29afaa6..30f34fe 100644
--- a/media/java/android/media/projection/MediaProjectionConfig.java
+++ b/media/java/android/media/projection/MediaProjectionConfig.java
@@ -98,24 +98,12 @@
}
/**
- * Returns an instance which restricts the user to capturing a particular display.
- *
- * @param displayId The id of the display to capture. Only supports values of
- * {@link android.view.Display#DEFAULT_DISPLAY}.
- * @throws IllegalArgumentException If the given {@code displayId} is outside the range of
- * supported values.
+ * Returns an instance which restricts the user to capturing the default display.
*/
@NonNull
- public static MediaProjectionConfig createConfigForDisplay(
- @IntRange(from = DEFAULT_DISPLAY, to = DEFAULT_DISPLAY) int displayId) {
- if (displayId != DEFAULT_DISPLAY) {
- throw new IllegalArgumentException(
- "A config for capturing the non-default display is not supported; requested "
- + "display id "
- + displayId);
- }
+ public static MediaProjectionConfig createConfigForDefaultDisplay() {
MediaProjectionConfig config = new MediaProjectionConfig(CAPTURE_REGION_FIXED_DISPLAY);
- config.mDisplayToCapture = displayId;
+ config.mDisplayToCapture = DEFAULT_DISPLAY;
return config;
}
@@ -279,10 +267,10 @@
};
@DataClass.Generated(
- time = 1671030124845L,
+ time = 1673548980960L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/media/java/android/media/projection/MediaProjectionConfig.java",
- inputSignatures = "public static final int CAPTURE_REGION_USER_CHOICE\npublic static final int CAPTURE_REGION_FIXED_DISPLAY\nprivate @android.annotation.IntRange int mDisplayToCapture\nprivate @android.media.projection.MediaProjectionConfig.CaptureRegion int mRegionToCapture\npublic static @android.annotation.NonNull android.media.projection.MediaProjectionConfig createConfigForDisplay(int)\npublic static @android.annotation.NonNull android.media.projection.MediaProjectionConfig createConfigForUserChoice()\nprivate static @android.annotation.NonNull java.lang.String captureRegionToString(int)\npublic @java.lang.Override java.lang.String toString()\nclass MediaProjectionConfig extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genAidl=true, genSetters=false, genConstructor=false, genBuilder=false, genToString=false, genHiddenConstDefs=true, genHiddenGetters=true, genConstDefs=false)")
+ inputSignatures = "public static final int CAPTURE_REGION_USER_CHOICE\npublic static final int CAPTURE_REGION_FIXED_DISPLAY\nprivate @android.annotation.IntRange int mDisplayToCapture\nprivate @android.media.projection.MediaProjectionConfig.CaptureRegion int mRegionToCapture\npublic static @android.annotation.NonNull android.media.projection.MediaProjectionConfig createConfigForDefaultDisplay()\npublic static @android.annotation.NonNull android.media.projection.MediaProjectionConfig createConfigForUserChoice()\nprivate static @android.annotation.NonNull java.lang.String captureRegionToString(int)\npublic @java.lang.Override java.lang.String toString()\nclass MediaProjectionConfig extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genAidl=true, genSetters=false, genConstructor=false, genBuilder=false, genToString=false, genHiddenConstDefs=true, genHiddenGetters=true, genConstDefs=false)")
@Deprecated
private void __metadata() {}
diff --git a/media/java/android/media/projection/MediaProjectionManager.java b/media/java/android/media/projection/MediaProjectionManager.java
index d60dfd9..6d65c26 100644
--- a/media/java/android/media/projection/MediaProjectionManager.java
+++ b/media/java/android/media/projection/MediaProjectionManager.java
@@ -109,8 +109,8 @@
* If {@link MediaProjectionConfig} was created from:
* <ul>
* <li>
- * {@link MediaProjectionConfig#createConfigForDisplay(int)}, then creates an
- * {@link Intent} for capturing this particular display. The activity limits the user's
+ * {@link MediaProjectionConfig#createConfigForDefaultDisplay()}, then creates an
+ * {@link Intent} for capturing the default display. The activity limits the user's
* choice to just the display specified.
* </li>
* <li>
diff --git a/media/java/android/media/projection/TEST_MAPPING b/media/java/android/media/projection/TEST_MAPPING
new file mode 100644
index 0000000..a792498
--- /dev/null
+++ b/media/java/android/media/projection/TEST_MAPPING
@@ -0,0 +1,18 @@
+{
+ "presubmit": [
+ {
+ "name": "MediaProjectionTests",
+ "options": [
+ {
+ "exclude-annotation": "android.platform.test.annotations.FlakyTest"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ },
+ {
+ "exclude-annotation": "org.junit.Ignore"
+ }
+ ]
+ }
+ ]
+}
diff --git a/media/java/android/media/tv/TableRequest.java b/media/java/android/media/tv/TableRequest.java
index a1a6b51..a9ea6d3 100644
--- a/media/java/android/media/tv/TableRequest.java
+++ b/media/java/android/media/tv/TableRequest.java
@@ -33,11 +33,54 @@
/** @hide */
@Retention(RetentionPolicy.SOURCE)
- @IntDef({TABLE_NAME_PAT, TABLE_NAME_PMT})
+ @IntDef({TABLE_NAME_PAT, TABLE_NAME_PMT, TABLE_NAME_CAT})
public @interface TableName {}
+ /** Program Association Table */
public static final int TABLE_NAME_PAT = 0;
+ /** Program Mapping Table */
public static final int TABLE_NAME_PMT = 1;
+ /**
+ * Conditional Access Table
+ * @hide
+ */
+ public static final int TABLE_NAME_CAT = 2;
+ /**
+ * Network Information Table
+ * @hide
+ */
+ public static final int TABLE_NAME_NIT = 3;
+ /**
+ * Bouquet Association Table
+ * @hide
+ */
+ public static final int TABLE_NAME_BAT = 4;
+ /**
+ * Service Description Table
+ * @hide
+ */
+ public static final int TABLE_NAME_SDT = 5;
+ /**
+ * Event Information Table
+ * @hide
+ */
+ public static final int TABLE_NAME_EIT = 6;
+ /**
+ * Time and Date Table
+ * @hide
+ */
+ public static final int TABLE_NAME_TDT = 7;
+ /**
+ * Time Offset Table
+ * @hide
+ */
+ public static final int TABLE_NAME_TOT = 8;
+ /**
+ * Selection Information Table
+ * @hide
+ */
+ public static final int TABLE_NAME_SIT = 9;
+
public static final @NonNull Parcelable.Creator<TableRequest> CREATOR =
new Parcelable.Creator<TableRequest>() {
diff --git a/media/java/android/media/tv/TableResponse.java b/media/java/android/media/tv/TableResponse.java
index afc9bee..1c314b0 100644
--- a/media/java/android/media/tv/TableResponse.java
+++ b/media/java/android/media/tv/TableResponse.java
@@ -21,6 +21,7 @@
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.SharedMemory;
/**
* A response for Table from broadcast signal.
@@ -46,6 +47,8 @@
private final Uri mTableUri;
private final int mVersion;
private final int mSize;
+ private final byte[] mTableByteArray;
+ private final SharedMemory mTableSharedMemory;
static TableResponse createFromParcelBody(Parcel in) {
return new TableResponse(in);
@@ -54,9 +57,33 @@
public TableResponse(int requestId, int sequence, @ResponseResult int responseResult,
@Nullable Uri tableUri, int version, int size) {
super(RESPONSE_TYPE, requestId, sequence, responseResult);
- mTableUri = tableUri;
mVersion = version;
mSize = size;
+ mTableUri = tableUri;
+ mTableByteArray = null;
+ mTableSharedMemory = null;
+ }
+
+ /** @hide */
+ public TableResponse(int requestId, int sequence, @ResponseResult int responseResult,
+ @NonNull byte[] tableByteArray, int version, int size) {
+ super(RESPONSE_TYPE, requestId, sequence, responseResult);
+ mVersion = version;
+ mSize = size;
+ mTableUri = null;
+ mTableByteArray = tableByteArray;
+ mTableSharedMemory = null;
+ }
+
+ /** @hide */
+ public TableResponse(int requestId, int sequence, @ResponseResult int responseResult,
+ @NonNull SharedMemory tableSharedMemory, int version, int size) {
+ super(RESPONSE_TYPE, requestId, sequence, responseResult);
+ mVersion = version;
+ mSize = size;
+ mTableUri = null;
+ mTableByteArray = null;
+ mTableSharedMemory = tableSharedMemory;
}
TableResponse(Parcel source) {
@@ -65,6 +92,14 @@
mTableUri = uriString == null ? null : Uri.parse(uriString);
mVersion = source.readInt();
mSize = source.readInt();
+ int arrayLength = source.readInt();
+ if (arrayLength >= 0) {
+ mTableByteArray = new byte[arrayLength];
+ source.readByteArray(mTableByteArray);
+ } else {
+ mTableByteArray = null;
+ }
+ mTableSharedMemory = (SharedMemory) source.readTypedObject(SharedMemory.CREATOR);
}
/**
@@ -76,6 +111,30 @@
}
/**
+ * Gets the data of the table as a byte array.
+ *
+ * @return the table data as a byte array, or {@code null} if the data is not stored as a byte
+ * array.
+ * @hide
+ */
+ @Nullable
+ public byte[] getTableByteArray() {
+ return mTableByteArray;
+ }
+
+ /**
+ * Gets the data of the table as a {@link SharedMemory} object.
+ *
+ * @return the table data as a {@link SharedMemory} object, or {@code null} if the data is not
+ * stored in shared memory.
+ * @hide
+ */
+ @Nullable
+ public SharedMemory getTableSharedMemory() {
+ return mTableSharedMemory;
+ }
+
+ /**
* Gets the version number of requested table. If it is null, value will be -1.
* <p>The consistency of version numbers between request and response depends on
* {@link BroadcastInfoRequest.RequestOption}. If the request has RequestOption value
@@ -106,5 +165,12 @@
dest.writeString(uriString);
dest.writeInt(mVersion);
dest.writeInt(mSize);
+ if (mTableByteArray != null) {
+ dest.writeInt(mTableByteArray.length);
+ dest.writeByteArray(mTableByteArray);
+ } else {
+ dest.writeInt(-1);
+ }
+ dest.writeTypedObject(mTableSharedMemory, flags);
}
}
diff --git a/media/java/android/media/tv/TimelineRequest.java b/media/java/android/media/tv/TimelineRequest.java
index 03c62f0..d04c58a 100644
--- a/media/java/android/media/tv/TimelineRequest.java
+++ b/media/java/android/media/tv/TimelineRequest.java
@@ -42,6 +42,7 @@
};
private final int mIntervalMillis;
+ private final String mSelector;
static TimelineRequest createFromParcelBody(Parcel in) {
return new TimelineRequest(in);
@@ -50,11 +51,21 @@
public TimelineRequest(int requestId, @RequestOption int option, int intervalMillis) {
super(REQUEST_TYPE, requestId, option);
mIntervalMillis = intervalMillis;
+ mSelector = null;
+ }
+
+ /** @hide */
+ public TimelineRequest(int requestId, @RequestOption int option, int intervalMillis,
+ @NonNull String selector) {
+ super(REQUEST_TYPE, requestId, option);
+ mIntervalMillis = intervalMillis;
+ mSelector = selector;
}
TimelineRequest(Parcel source) {
super(REQUEST_TYPE, source);
mIntervalMillis = source.readInt();
+ mSelector = source.readString();
}
/**
@@ -64,6 +75,18 @@
return mIntervalMillis;
}
+ /**
+ * Gets the timeline selector.
+ * <p>The selector describes the type and location of timeline signalling. For example
+ * {@code urn:dvb:css:timeline:pts} is a selector in DVB standard.
+ *
+ * @return the selector if it's set; {@code null} otherwise.
+ * @hide
+ */
+ public String getSelector() {
+ return mSelector;
+ }
+
@Override
public int describeContents() {
return 0;
@@ -73,5 +96,6 @@
public void writeToParcel(@NonNull Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeInt(mIntervalMillis);
+ dest.writeString(mSelector);
}
}
diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppClient.aidl b/media/java/android/media/tv/interactive/ITvInteractiveAppClient.aidl
index 537e711..ad9312f 100644
--- a/media/java/android/media/tv/interactive/ITvInteractiveAppClient.aidl
+++ b/media/java/android/media/tv/interactive/ITvInteractiveAppClient.aidl
@@ -41,7 +41,9 @@
void onTeletextAppStateChanged(int state, int seq);
void onAdBuffer(in AdBuffer buffer, int seq);
void onCommandRequest(in String cmdType, in Bundle parameters, int seq);
+ void onTimeShiftCommandRequest(in String cmdType, in Bundle parameters, int seq);
void onSetVideoBounds(in Rect rect, int seq);
+ void onRequestCurrentVideoBounds(int seq);
void onRequestCurrentChannelUri(int seq);
void onRequestCurrentChannelLcn(int seq);
void onRequestStreamVolume(int seq);
diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl b/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl
index 5a0ac84..c0723f7 100644
--- a/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl
+++ b/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl
@@ -26,6 +26,7 @@
import android.media.tv.interactive.ITvInteractiveAppClient;
import android.media.tv.interactive.ITvInteractiveAppManagerCallback;
import android.media.tv.interactive.TvInteractiveAppServiceInfo;
+import android.media.PlaybackParams;
import android.net.Uri;
import android.os.Bundle;
import android.view.Surface;
@@ -36,6 +37,7 @@
*/
interface ITvInteractiveAppManager {
List<TvInteractiveAppServiceInfo> getTvInteractiveAppServiceList(int userId);
+ List<AppLinkInfo> getAppLinkInfoList(int userId);
void registerAppLinkInfo(String tiasId, in AppLinkInfo info, int userId);
void unregisterAppLinkInfo(String tiasId, in AppLinkInfo info, int userId);
void sendAppLinkCommand(String tiasId, in Bundle command, int userId);
@@ -46,6 +48,7 @@
in IBinder sessionToken, in Uri biIAppUri, in Bundle params, int userId);
void destroyBiInteractiveApp(in IBinder sessionToken, in String biIAppId, int userId);
void setTeletextAppEnabled(in IBinder sessionToken, boolean enable, int userId);
+ void sendCurrentVideoBounds(in IBinder sessionToken, in Rect bounds, int userId);
void sendCurrentChannelUri(in IBinder sessionToken, in Uri channelUri, int userId);
void sendCurrentChannelLcn(in IBinder sessionToken, int lcn, int userId);
void sendStreamVolume(in IBinder sessionToken, float volume, int userId);
@@ -57,6 +60,14 @@
void sendTvRecordingInfoList(in IBinder sessionToken,
in List<TvRecordingInfo> recordingInfoList, int userId);
void notifyError(in IBinder sessionToken, in String errMsg, in Bundle params, int userId);
+ void notifyTimeShiftPlaybackParams(
+ in IBinder sessionToken, in PlaybackParams params, int userId);
+ void notifyTimeShiftStatusChanged(
+ in IBinder sessionToken, in String inputId, int status, int userId);
+ void notifyTimeShiftStartPositionChanged(
+ in IBinder sessionToken, in String inputId, long timeMs, int userId);
+ void notifyTimeShiftCurrentPositionChanged(
+ in IBinder sessionToken, in String inputId, long timeMs, int userId);
void createSession(in ITvInteractiveAppClient client, in String iAppServiceId, int type,
int seq, int userId);
void releaseSession(in IBinder sessionToken, int userId);
diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppSession.aidl b/media/java/android/media/tv/interactive/ITvInteractiveAppSession.aidl
index 20ba57b..9ae9ca7 100644
--- a/media/java/android/media/tv/interactive/ITvInteractiveAppSession.aidl
+++ b/media/java/android/media/tv/interactive/ITvInteractiveAppSession.aidl
@@ -20,6 +20,7 @@
import android.media.tv.BroadcastInfoResponse;
import android.net.Uri;
import android.media.tv.AdBuffer;
+import android.media.PlaybackParams;
import android.media.tv.AdResponse;
import android.media.tv.BroadcastInfoResponse;
import android.media.tv.TvTrackInfo;
@@ -39,6 +40,7 @@
void createBiInteractiveApp(in Uri biIAppUri, in Bundle params);
void destroyBiInteractiveApp(in String biIAppId);
void setTeletextAppEnabled(boolean enable);
+ void sendCurrentVideoBounds(in Rect bounds);
void sendCurrentChannelUri(in Uri channelUri);
void sendCurrentChannelLcn(int lcn);
void sendStreamVolume(float volume);
@@ -48,6 +50,10 @@
void sendTvRecordingInfo(in TvRecordingInfo recordingInfo);
void sendTvRecordingInfoList(in List<TvRecordingInfo> recordingInfoList);
void notifyError(in String errMsg, in Bundle params);
+ void notifyTimeShiftPlaybackParams(in PlaybackParams params);
+ void notifyTimeShiftStatusChanged(in String inputId, int status);
+ void notifyTimeShiftStartPositionChanged(in String inputId, long timeMs);
+ void notifyTimeShiftCurrentPositionChanged(in String inputId, long timeMs);
void release();
void notifyTuned(in Uri channelUri);
void notifyTrackSelected(int type, in String trackId);
diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppSessionCallback.aidl b/media/java/android/media/tv/interactive/ITvInteractiveAppSessionCallback.aidl
index c5dbd19..d84affd 100644
--- a/media/java/android/media/tv/interactive/ITvInteractiveAppSessionCallback.aidl
+++ b/media/java/android/media/tv/interactive/ITvInteractiveAppSessionCallback.aidl
@@ -40,7 +40,9 @@
void onTeletextAppStateChanged(int state);
void onAdBuffer(in AdBuffer buffer);
void onCommandRequest(in String cmdType, in Bundle parameters);
+ void onTimeShiftCommandRequest(in String cmdType, in Bundle parameters);
void onSetVideoBounds(in Rect rect);
+ void onRequestCurrentVideoBounds();
void onRequestCurrentChannelUri();
void onRequestCurrentChannelLcn();
void onRequestStreamVolume();
diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java b/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java
index a55e1ac..8a23e65 100644
--- a/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java
+++ b/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java
@@ -20,6 +20,7 @@
import android.annotation.Nullable;
import android.content.Context;
import android.graphics.Rect;
+import android.media.PlaybackParams;
import android.media.tv.AdBuffer;
import android.media.tv.AdResponse;
import android.media.tv.BroadcastInfoResponse;
@@ -89,6 +90,11 @@
private static final int DO_NOTIFY_TV_MESSAGE = 33;
private static final int DO_SEND_RECORDING_INFO = 34;
private static final int DO_SEND_RECORDING_INFO_LIST = 35;
+ private static final int DO_NOTIFY_TIME_SHIFT_PLAYBACK_PARAMS = 36;
+ private static final int DO_NOTIFY_TIME_SHIFT_STATUS_CHANGED = 37;
+ private static final int DO_NOTIFY_TIME_SHIFT_START_POSITION_CHANGED = 38;
+ private static final int DO_NOTIFY_TIME_SHIFT_CURRENT_POSITION_CHANGED = 39;
+ private static final int DO_SEND_CURRENT_VIDEO_BOUNDS = 40;
private final HandlerCaller mCaller;
private Session mSessionImpl;
@@ -152,6 +158,10 @@
mSessionImpl.setTeletextAppEnabled((Boolean) msg.obj);
break;
}
+ case DO_SEND_CURRENT_VIDEO_BOUNDS: {
+ mSessionImpl.sendCurrentVideoBounds((Rect) msg.obj);
+ break;
+ }
case DO_SEND_CURRENT_CHANNEL_URI: {
mSessionImpl.sendCurrentChannelUri((Uri) msg.obj);
break;
@@ -277,6 +287,30 @@
mSessionImpl.notifyAdBufferConsumed((AdBuffer) msg.obj);
break;
}
+ case DO_NOTIFY_TIME_SHIFT_PLAYBACK_PARAMS: {
+ mSessionImpl.notifyTimeShiftPlaybackParams((PlaybackParams) msg.obj);
+ break;
+ }
+ case DO_NOTIFY_TIME_SHIFT_STATUS_CHANGED: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ mSessionImpl.notifyTimeShiftStatusChanged((String) args.arg1, (Integer) args.arg2);
+ args.recycle();
+ break;
+ }
+ case DO_NOTIFY_TIME_SHIFT_START_POSITION_CHANGED: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ mSessionImpl.notifyTimeShiftStartPositionChanged(
+ (String) args.arg1, (Long) args.arg2);
+ args.recycle();
+ break;
+ }
+ case DO_NOTIFY_TIME_SHIFT_CURRENT_POSITION_CHANGED: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ mSessionImpl.notifyTimeShiftCurrentPositionChanged(
+ (String) args.arg1, (Long) args.arg2);
+ args.recycle();
+ break;
+ }
default: {
Log.w(TAG, "Unhandled message code: " + msg.what);
break;
@@ -326,6 +360,12 @@
}
@Override
+ public void sendCurrentVideoBounds(@Nullable Rect bounds) {
+ mCaller.executeOrSendMessage(
+ mCaller.obtainMessageO(DO_SEND_CURRENT_VIDEO_BOUNDS, bounds));
+ }
+
+ @Override
public void sendCurrentChannelUri(@Nullable Uri channelUri) {
mCaller.executeOrSendMessage(
mCaller.obtainMessageO(DO_SEND_CURRENT_CHANNEL_URI, channelUri));
@@ -380,6 +420,30 @@
}
@Override
+ public void notifyTimeShiftPlaybackParams(@NonNull PlaybackParams params) {
+ mCaller.executeOrSendMessage(
+ mCaller.obtainMessageO(DO_NOTIFY_TIME_SHIFT_PLAYBACK_PARAMS, params));
+ }
+
+ @Override
+ public void notifyTimeShiftStatusChanged(@NonNull String inputId, int status) {
+ mCaller.executeOrSendMessage(
+ mCaller.obtainMessageOO(DO_NOTIFY_TIME_SHIFT_STATUS_CHANGED, inputId, status));
+ }
+
+ @Override
+ public void notifyTimeShiftStartPositionChanged(@NonNull String inputId, long timeMs) {
+ mCaller.executeOrSendMessage(mCaller.obtainMessageOO(
+ DO_NOTIFY_TIME_SHIFT_START_POSITION_CHANGED, inputId, timeMs));
+ }
+
+ @Override
+ public void notifyTimeShiftCurrentPositionChanged(@NonNull String inputId, long timeMs) {
+ mCaller.executeOrSendMessage(mCaller.obtainMessageOO(
+ DO_NOTIFY_TIME_SHIFT_CURRENT_POSITION_CHANGED, inputId, timeMs));
+ }
+
+ @Override
public void release() {
mSessionImpl.scheduleMediaViewCleanup();
mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_RELEASE));
diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppManager.java b/media/java/android/media/tv/interactive/TvInteractiveAppManager.java
index f4847f7..fd3c29b 100755
--- a/media/java/android/media/tv/interactive/TvInteractiveAppManager.java
+++ b/media/java/android/media/tv/interactive/TvInteractiveAppManager.java
@@ -23,6 +23,7 @@
import android.annotation.SystemService;
import android.content.Context;
import android.graphics.Rect;
+import android.media.PlaybackParams;
import android.media.tv.AdBuffer;
import android.media.tv.AdRequest;
import android.media.tv.AdResponse;
@@ -405,6 +406,21 @@
}
@Override
+ public void onTimeShiftCommandRequest(
+ @TvInteractiveAppService.TimeShiftCommandType String cmdType,
+ Bundle parameters,
+ int seq) {
+ synchronized (mSessionCallbackRecordMap) {
+ SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
+ if (record == null) {
+ Log.e(TAG, "Callback not found for seq " + seq);
+ return;
+ }
+ record.postTimeShiftCommandRequest(cmdType, parameters);
+ }
+ }
+
+ @Override
public void onSetVideoBounds(Rect rect, int seq) {
synchronized (mSessionCallbackRecordMap) {
SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
@@ -429,6 +445,18 @@
}
@Override
+ public void onRequestCurrentVideoBounds(int seq) {
+ synchronized (mSessionCallbackRecordMap) {
+ SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
+ if (record == null) {
+ Log.e(TAG, "Callback not found for seq " + seq);
+ return;
+ }
+ record.postRequestCurrentVideoBounds();
+ }
+ }
+
+ @Override
public void onRequestCurrentChannelUri(int seq) {
synchronized (mSessionCallbackRecordMap) {
SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
@@ -849,6 +877,24 @@
}
/**
+ * Returns a list of available app link information.
+ *
+ * <P>A package must declare its app link info in its manifest using meta-data tag, so the info
+ * can be detected by the system.
+ *
+ * @return List of {@link AppLinkInfo} for each package that deslares its app link information.
+ * @hide
+ */
+ @NonNull
+ public List<AppLinkInfo> getAppLinkInfoList() {
+ try {
+ return mService.getAppLinkInfoList(mUserId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Registers an Android application link info record which can be used to launch the specific
* Android application by TV interactive App RTE.
*
@@ -1050,6 +1096,18 @@
}
}
+ void sendCurrentVideoBounds(@NonNull Rect bounds) {
+ if (mToken == null) {
+ Log.w(TAG, "The session has been already released");
+ return;
+ }
+ try {
+ mService.sendCurrentVideoBounds(mToken, bounds, mUserId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
void sendCurrentChannelUri(@Nullable Uri channelUri) {
if (mToken == null) {
Log.w(TAG, "The session has been already released");
@@ -1182,6 +1240,55 @@
}
}
+ void notifyTimeShiftPlaybackParams(@NonNull PlaybackParams params) {
+ if (mToken == null) {
+ Log.w(TAG, "The session has been already released");
+ return;
+ }
+ try {
+ mService.notifyTimeShiftPlaybackParams(mToken, params, mUserId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ void notifyTimeShiftStatusChanged(
+ @NonNull String inputId, @TvInputManager.TimeShiftStatus int status) {
+ if (mToken == null) {
+ Log.w(TAG, "The session has been already released");
+ return;
+ }
+ try {
+ mService.notifyTimeShiftStatusChanged(mToken, inputId, status, mUserId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ void notifyTimeShiftStartPositionChanged(@NonNull String inputId, long timeMs) {
+ if (mToken == null) {
+ Log.w(TAG, "The session has been already released");
+ return;
+ }
+ try {
+ mService.notifyTimeShiftStartPositionChanged(mToken, inputId, timeMs, mUserId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ void notifyTimeShiftCurrentPositionChanged(@NonNull String inputId, long timeMs) {
+ if (mToken == null) {
+ Log.w(TAG, "The session has been already released");
+ return;
+ }
+ try {
+ mService.notifyTimeShiftCurrentPositionChanged(mToken, inputId, timeMs, mUserId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
/**
* Sets the {@link android.view.Surface} for this session.
*
@@ -1795,6 +1902,17 @@
});
}
+ void postTimeShiftCommandRequest(
+ final @TvInteractiveAppService.TimeShiftCommandType String cmdType,
+ final Bundle parameters) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mSessionCallback.onTimeShiftCommandRequest(mSession, cmdType, parameters);
+ }
+ });
+ }
+
void postSetVideoBounds(Rect rect) {
mHandler.post(new Runnable() {
@Override
@@ -1804,6 +1922,15 @@
});
}
+ void postRequestCurrentVideoBounds() {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mSessionCallback.onRequestCurrentVideoBounds(mSession);
+ }
+ });
+ }
+
void postRequestCurrentChannelUri() {
mHandler.post(new Runnable() {
@Override
@@ -2003,6 +2130,20 @@
}
/**
+ * This is called when {@link TvInteractiveAppService.Session#requestTimeShiftCommand} is
+ * called.
+ *
+ * @param session A {@link TvInteractiveAppManager.Session} associated with this callback.
+ * @param cmdType type of the time shift command.
+ * @param parameters parameters of the command.
+ */
+ public void onTimeShiftCommandRequest(
+ Session session,
+ @TvInteractiveAppService.TimeShiftCommandType String cmdType,
+ Bundle parameters) {
+ }
+
+ /**
* This is called when {@link TvInteractiveAppService.Session#SetVideoBounds} is called.
*
* @param session A {@link TvInteractiveAppManager.Session} associated with this callback.
@@ -2011,6 +2152,15 @@
}
/**
+ * This is called when {@link TvInteractiveAppService.Session#RequestCurrentVideoBounds} is
+ * called.
+ *
+ * @param session A {@link TvInteractiveAppManager.Session} associated with this callback.
+ */
+ public void onRequestCurrentVideoBounds(Session session) {
+ }
+
+ /**
* This is called when {@link TvInteractiveAppService.Session#RequestCurrentChannelUri} is
* called.
*
diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppService.java b/media/java/android/media/tv/interactive/TvInteractiveAppService.java
index 3ca9f2f..be2c16c 100755
--- a/media/java/android/media/tv/interactive/TvInteractiveAppService.java
+++ b/media/java/android/media/tv/interactive/TvInteractiveAppService.java
@@ -17,6 +17,7 @@
package android.media.tv.interactive;
import android.annotation.CallSuper;
+import android.annotation.IntDef;
import android.annotation.MainThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -30,6 +31,7 @@
import android.content.Intent;
import android.graphics.PixelFormat;
import android.graphics.Rect;
+import android.media.PlaybackParams;
import android.media.tv.AdBuffer;
import android.media.tv.AdRequest;
import android.media.tv.AdResponse;
@@ -138,6 +140,38 @@
* Playback command type: select the given track.
*/
public static final String PLAYBACK_COMMAND_TYPE_SELECT_TRACK = "select_track";
+
+
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = "PLAYBACK_COMMAND_STOP_MODE_", value = {
+ PLAYBACK_COMMAND_STOP_MODE_BLANK,
+ PLAYBACK_COMMAND_STOP_MODE_FREEZE
+ })
+ public @interface PlaybackCommandStopMode {}
+
+ /**
+ * Playback command stop mode: show a blank screen.
+ * @hide
+ */
+ public static final int PLAYBACK_COMMAND_STOP_MODE_BLANK = 1;
+
+ /**
+ * Playback command stop mode: freeze the video.
+ * @hide
+ */
+ public static final int PLAYBACK_COMMAND_STOP_MODE_FREEZE = 2;
+
+ /**
+ * Playback command parameter: stop mode.
+ * <p>Type: int
+ *
+ * @see #PLAYBACK_COMMAND_TYPE_STOP
+ * @hide
+ */
+ public static final String COMMAND_PARAMETER_KEY_STOP_MODE = "command_stop_mode";
+
/**
* Playback command parameter: channel URI.
* <p>Type: android.net.Uri
@@ -182,6 +216,78 @@
public static final String COMMAND_PARAMETER_KEY_CHANGE_CHANNEL_QUIETLY =
"command_change_channel_quietly";
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @StringDef(prefix = "TIME_SHIFT_COMMAND_TYPE_", value = {
+ TIME_SHIFT_COMMAND_TYPE_PLAY,
+ TIME_SHIFT_COMMAND_TYPE_PAUSE,
+ TIME_SHIFT_COMMAND_TYPE_RESUME,
+ TIME_SHIFT_COMMAND_TYPE_SEEK_TO,
+ TIME_SHIFT_COMMAND_TYPE_SET_PLAYBACK_PARAMS,
+ })
+ public @interface TimeShiftCommandType {}
+
+ /**
+ * Time shift command type: play.
+ *
+ * @see TvView#timeShiftPlay(String, Uri)
+ * @hide
+ */
+ public static final String TIME_SHIFT_COMMAND_TYPE_PLAY = "play";
+ /**
+ * Time shift command type: pause.
+ *
+ * @see TvView#timeShiftPause()
+ * @hide
+ */
+ public static final String TIME_SHIFT_COMMAND_TYPE_PAUSE = "pause";
+ /**
+ * Time shift command type: resume.
+ *
+ * @see TvView#timeShiftResume()
+ * @hide
+ */
+ public static final String TIME_SHIFT_COMMAND_TYPE_RESUME = "resume";
+ /**
+ * Time shift command type: seek to.
+ *
+ * @see TvView#timeShiftSeekTo(long)
+ * @hide
+ */
+ public static final String TIME_SHIFT_COMMAND_TYPE_SEEK_TO = "seek_to";
+ /**
+ * Time shift command type: set playback params.
+ *
+ * @see TvView#timeShiftSetPlaybackParams(PlaybackParams)
+ * @hide
+ */
+ public static final String TIME_SHIFT_COMMAND_TYPE_SET_PLAYBACK_PARAMS = "set_playback_params";
+
+ /**
+ * Time shift command parameter: program URI.
+ * <p>Type: android.net.Uri
+ *
+ * @see #TIME_SHIFT_COMMAND_TYPE_PLAY
+ * @hide
+ */
+ public static final String COMMAND_PARAMETER_KEY_PROGRAM_URI = "command_program_uri";
+ /**
+ * Time shift command parameter: time position for time shifting, in milliseconds.
+ * <p>Type: long
+ *
+ * @see #TIME_SHIFT_COMMAND_TYPE_SEEK_TO
+ * @hide
+ */
+ public static final String COMMAND_PARAMETER_KEY_TIME_POSITION = "command_time_position";
+ /**
+ * Time shift command parameter: playback params.
+ * <p>Type: android.media.PlaybackParams
+ *
+ * @see #TIME_SHIFT_COMMAND_TYPE_SET_PLAYBACK_PARAMS
+ * @hide
+ */
+ public static final String COMMAND_PARAMETER_KEY_PLAYBACK_PARAMS = "command_playback_params";
+
private final Handler mServiceHandler = new ServiceHandler();
private final RemoteCallbackList<ITvInteractiveAppServiceCallback> mCallbacks =
new RemoteCallbackList<>();
@@ -425,6 +531,13 @@
}
/**
+ * Receives current video bounds.
+ * @hide
+ */
+ public void onCurrentVideoBounds(@NonNull Rect bounds) {
+ }
+
+ /**
* Receives current channel URI.
*/
public void onCurrentChannelUri(@Nullable Uri channelUri) {
@@ -520,6 +633,44 @@
}
/**
+ * Called when the time shift {@link android.media.PlaybackParams} is set or changed.
+ *
+ * @see TvView#timeShiftSetPlaybackParams(PlaybackParams)
+ * @hide
+ */
+ public void onTimeShiftPlaybackParams(@NonNull PlaybackParams params) {
+ }
+
+ /**
+ * Called when time shift status is changed.
+ *
+ * @see TvView.TvInputCallback#onTimeShiftStatusChanged(String, int)
+ * @see android.media.tv.TvInputService.Session#notifyTimeShiftStatusChanged(int)
+ * @hide
+ */
+ public void onTimeShiftStatusChanged(
+ @NonNull String inputId, @TvInputManager.TimeShiftStatus int status) {
+ }
+
+ /**
+ * Called when time shift start position is changed.
+ *
+ * @see TvView.TimeShiftPositionCallback#onTimeShiftStartPositionChanged(String, long)
+ * @hide
+ */
+ public void onTimeShiftStartPositionChanged(@NonNull String inputId, long timeMs) {
+ }
+
+ /**
+ * Called when time shift current position is changed.
+ *
+ * @see TvView.TimeShiftPositionCallback#onTimeShiftCurrentPositionChanged(String, long)
+ * @hide
+ */
+ public void onTimeShiftCurrentPositionChanged(@NonNull String inputId, long timeMs) {
+ }
+
+ /**
* Called when the application sets the surface.
*
* <p>The TV Interactive App service should render interactive app UI onto the given
@@ -820,6 +971,35 @@
}
/**
+ * Sends a specific time shift command to be processed by the related TV input.
+ *
+ * @param cmdType type of the specific command
+ * @param parameters parameters of the specific command
+ * @hide
+ */
+ @CallSuper
+ public void sendTimeShiftCommandRequest(
+ @TimeShiftCommandType @NonNull String cmdType, @Nullable Bundle parameters) {
+ executeOrPostRunnableOnMainThread(new Runnable() {
+ @MainThread
+ @Override
+ public void run() {
+ try {
+ if (DEBUG) {
+ Log.d(TAG, "requestTimeShiftCommand (cmdType=" + cmdType
+ + ", parameters=" + parameters.toString() + ")");
+ }
+ if (mSessionCallback != null) {
+ mSessionCallback.onTimeShiftCommandRequest(cmdType, parameters);
+ }
+ } catch (RemoteException e) {
+ Log.w(TAG, "error in requestTimeShiftCommand", e);
+ }
+ }
+ });
+ }
+
+ /**
* Sets broadcast video bounds.
*/
@CallSuper
@@ -843,6 +1023,30 @@
}
/**
+ * Requests the bounds of the current video.
+ * @hide
+ */
+ @CallSuper
+ public void requestCurrentVideoBounds() {
+ executeOrPostRunnableOnMainThread(new Runnable() {
+ @MainThread
+ @Override
+ public void run() {
+ try {
+ if (DEBUG) {
+ Log.d(TAG, "requestCurrentVideoBounds");
+ }
+ if (mSessionCallback != null) {
+ mSessionCallback.onRequestCurrentVideoBounds();
+ }
+ } catch (RemoteException e) {
+ Log.w(TAG, "error in requestCurrentVideoBounds", e);
+ }
+ }
+ });
+ }
+
+ /**
* Requests the URI of the current channel.
*/
@CallSuper
@@ -1169,6 +1373,10 @@
onSetTeletextAppEnabled(enable);
}
+ void sendCurrentVideoBounds(@NonNull Rect bounds) {
+ onCurrentVideoBounds(bounds);
+ }
+
void sendCurrentChannelUri(@Nullable Uri channelUri) {
onCurrentChannelUri(channelUri);
}
@@ -1330,6 +1538,34 @@
}
/**
+ * Calls {@link #onTimeShiftPlaybackParams(PlaybackParams)}.
+ */
+ void notifyTimeShiftPlaybackParams(PlaybackParams params) {
+ onTimeShiftPlaybackParams(params);
+ }
+
+ /**
+ * Calls {@link #onTimeShiftStatusChanged(String, int)}.
+ */
+ void notifyTimeShiftStatusChanged(String inputId, int status) {
+ onTimeShiftStatusChanged(inputId, status);
+ }
+
+ /**
+ * Calls {@link #onTimeShiftStartPositionChanged(String, long)}.
+ */
+ void notifyTimeShiftStartPositionChanged(String inputId, long timeMs) {
+ onTimeShiftStartPositionChanged(inputId, timeMs);
+ }
+
+ /**
+ * Calls {@link #onTimeShiftCurrentPositionChanged(String, long)}.
+ */
+ void notifyTimeShiftCurrentPositionChanged(String inputId, long timeMs) {
+ onTimeShiftCurrentPositionChanged(inputId, timeMs);
+ }
+
+ /**
* Notifies when the session state is changed.
*
* @param state the current session state.
diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppServiceInfo.java b/media/java/android/media/tv/interactive/TvInteractiveAppServiceInfo.java
index 3e08852..acc2444 100644
--- a/media/java/android/media/tv/interactive/TvInteractiveAppServiceInfo.java
+++ b/media/java/android/media/tv/interactive/TvInteractiveAppServiceInfo.java
@@ -57,6 +57,8 @@
INTERACTIVE_APP_TYPE_HBBTV,
INTERACTIVE_APP_TYPE_ATSC,
INTERACTIVE_APP_TYPE_GINGA,
+ INTERACTIVE_APP_TYPE_TARGETED_AD,
+ INTERACTIVE_APP_TYPE_OTHER
})
public @interface InteractiveAppType {}
@@ -66,10 +68,21 @@
public static final int INTERACTIVE_APP_TYPE_ATSC = 0x2;
/** Ginga interactive app type */
public static final int INTERACTIVE_APP_TYPE_GINGA = 0x4;
+ /**
+ * Targeted Advertisement interactive app type
+ * @hide
+ */
+ public static final int INTERACTIVE_APP_TYPE_TARGETED_AD = 0x8;
+ /**
+ * Other interactive app type
+ * @hide
+ */
+ public static final int INTERACTIVE_APP_TYPE_OTHER = 0x80000000;
private final ResolveInfo mService;
private final String mId;
private int mTypes;
+ private final List<String> mExtraTypes = new ArrayList<>();
/**
* Constructs a TvInteractiveAppServiceInfo object.
@@ -98,18 +111,21 @@
mService = resolveInfo;
mId = id;
- mTypes = toTypesFlag(types);
+ toTypesFlag(types);
}
- private TvInteractiveAppServiceInfo(ResolveInfo service, String id, int types) {
+ private TvInteractiveAppServiceInfo(
+ ResolveInfo service, String id, int types, List<String> extraTypes) {
mService = service;
mId = id;
mTypes = types;
+ mExtraTypes.addAll(extraTypes);
}
private TvInteractiveAppServiceInfo(@NonNull Parcel in) {
mService = ResolveInfo.CREATOR.createFromParcel(in);
mId = in.readString();
mTypes = in.readInt();
+ in.readStringList(mExtraTypes);
}
public static final @NonNull Creator<TvInteractiveAppServiceInfo> CREATOR =
@@ -135,6 +151,7 @@
mService.writeToParcel(dest, flags);
dest.writeString(mId);
dest.writeInt(mTypes);
+ dest.writeStringList(mExtraTypes);
}
/**
@@ -171,6 +188,17 @@
return mTypes;
}
+ /**
+ * Gets extra supported interactive app types which are not listed.
+ *
+ * @see #getSupportedTypes()
+ * @hide
+ */
+ @NonNull
+ public List<String> getExtraSupportedTypes() {
+ return mExtraTypes;
+ }
+
private static String generateInteractiveAppServiceId(ComponentName name) {
return name.flattenToShortString();
}
@@ -219,23 +247,27 @@
}
}
- private static int toTypesFlag(List<String> types) {
- int flag = 0;
+ private void toTypesFlag(List<String> types) {
+ mTypes = 0;
+ mExtraTypes.clear();
for (String type : types) {
switch (type) {
case "hbbtv":
- flag |= INTERACTIVE_APP_TYPE_HBBTV;
+ mTypes |= INTERACTIVE_APP_TYPE_HBBTV;
break;
case "atsc":
- flag |= INTERACTIVE_APP_TYPE_ATSC;
+ mTypes |= INTERACTIVE_APP_TYPE_ATSC;
break;
case "ginga":
- flag |= INTERACTIVE_APP_TYPE_GINGA;
+ mTypes |= INTERACTIVE_APP_TYPE_GINGA;
break;
+ case "targeted_ad":
+ mTypes |= INTERACTIVE_APP_TYPE_TARGETED_AD;
default:
+ mTypes |= INTERACTIVE_APP_TYPE_OTHER;
+ mExtraTypes.add(type);
break;
}
}
- return flag;
}
}
diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppView.java b/media/java/android/media/tv/interactive/TvInteractiveAppView.java
index 6777d1a..af03bb8 100755
--- a/media/java/android/media/tv/interactive/TvInteractiveAppView.java
+++ b/media/java/android/media/tv/interactive/TvInteractiveAppView.java
@@ -25,6 +25,7 @@
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.RectF;
+import android.media.PlaybackParams;
import android.media.tv.TvInputManager;
import android.media.tv.TvRecordingInfo;
import android.media.tv.TvTrackInfo;
@@ -513,6 +514,19 @@
}
/**
+ * Sends current video bounds to related TV interactive app.
+ * @hide
+ */
+ public void sendCurrentVideoBounds(@NonNull Rect bounds) {
+ if (DEBUG) {
+ Log.d(TAG, "sendCurrentVideoBounds");
+ }
+ if (mSession != null) {
+ mSession.sendCurrentVideoBounds(bounds);
+ }
+ }
+
+ /**
* Sends current channel URI to related TV interactive app.
*
* @param channelUri The current channel URI; {@code null} if there is no currently tuned
@@ -684,6 +698,75 @@
}
}
+ /**
+ * Notifies the corresponding {@link TvInteractiveAppService} when a time shift
+ * {@link android.media.PlaybackParams} is set or changed.
+ *
+ * @see TvView#timeShiftSetPlaybackParams(PlaybackParams)
+ * @hide
+ */
+ public void notifyTimeShiftPlaybackParams(@NonNull PlaybackParams params) {
+ if (DEBUG) {
+ Log.d(TAG, "notifyTimeShiftPlaybackParams params=" + params);
+ }
+ if (mSession != null) {
+ mSession.notifyTimeShiftPlaybackParams(params);
+ }
+ }
+
+ /**
+ * Notifies the corresponding {@link TvInteractiveAppService} when time shift
+ * status is changed.
+ *
+ * @see TvView.TvInputCallback#onTimeShiftStatusChanged(String, int)
+ * @see android.media.tv.TvInputService.Session#notifyTimeShiftStatusChanged(int)
+ * @hide
+ */
+ public void notifyTimeShiftStatusChanged(
+ @NonNull String inputId, @TvInputManager.TimeShiftStatus int status) {
+ if (DEBUG) {
+ Log.d(TAG,
+ "notifyTimeShiftStatusChanged inputId=" + inputId + "; status=" + status);
+ }
+ if (mSession != null) {
+ mSession.notifyTimeShiftStatusChanged(inputId, status);
+ }
+ }
+
+ /**
+ * Notifies the corresponding {@link TvInteractiveAppService} when time shift
+ * start position is changed.
+ *
+ * @see TvView.TimeShiftPositionCallback#onTimeShiftStartPositionChanged(String, long)
+ * @hide
+ */
+ public void notifyTimeShiftStartPositionChanged(@NonNull String inputId, long timeMs) {
+ if (DEBUG) {
+ Log.d(TAG, "notifyTimeShiftStartPositionChanged inputId=" + inputId
+ + "; timeMs=" + timeMs);
+ }
+ if (mSession != null) {
+ mSession.notifyTimeShiftStartPositionChanged(inputId, timeMs);
+ }
+ }
+
+ /**
+ * Notifies the corresponding {@link TvInteractiveAppService} when time shift
+ * current position is changed.
+ *
+ * @see TvView.TimeShiftPositionCallback#onTimeShiftCurrentPositionChanged(String, long)
+ * @hide
+ */
+ public void notifyTimeShiftCurrentPositionChanged(@NonNull String inputId, long timeMs) {
+ if (DEBUG) {
+ Log.d(TAG, "notifyTimeShiftCurrentPositionChanged inputId=" + inputId
+ + "; timeMs=" + timeMs);
+ }
+ if (mSession != null) {
+ mSession.notifyTimeShiftCurrentPositionChanged(inputId, timeMs);
+ }
+ }
+
private void resetInternal() {
mSessionCallback = null;
if (mSession != null) {
@@ -808,6 +891,21 @@
}
/**
+ * This is called when a time shift command is requested to be processed by the related TV
+ * input.
+ *
+ * @param iAppServiceId The ID of the TV interactive app service bound to this view.
+ * @param cmdType type of the command
+ * @param parameters parameters of the command
+ * @hide
+ */
+ public void onTimeShiftCommandRequest(
+ @NonNull String iAppServiceId,
+ @NonNull @TvInteractiveAppService.TimeShiftCommandType String cmdType,
+ @NonNull Bundle parameters) {
+ }
+
+ /**
* This is called when the state of corresponding interactive app is changed.
*
* @param iAppServiceId The ID of the TV interactive app service bound to this view.
@@ -859,6 +957,16 @@
}
/**
+ * This is called when {@link TvInteractiveAppService.Session#requestCurrentVideoBounds()}
+ * is called.
+ *
+ * @param iAppServiceId The ID of the TV interactive app service bound to this view.
+ * @hide
+ */
+ public void onRequestCurrentVideoBounds(@NonNull String iAppServiceId) {
+ }
+
+ /**
* This is called when {@link TvInteractiveAppService.Session#requestCurrentChannelUri()} is
* called.
*
@@ -1068,6 +1176,33 @@
}
@Override
+ public void onTimeShiftCommandRequest(
+ Session session,
+ @TvInteractiveAppService.TimeShiftCommandType String cmdType,
+ Bundle parameters) {
+ if (DEBUG) {
+ Log.d(TAG, "onTimeShiftCommandRequest (cmdType=" + cmdType + ", parameters="
+ + parameters.toString() + ")");
+ }
+ if (this != mSessionCallback) {
+ Log.w(TAG, "onTimeShiftCommandRequest - session not created");
+ return;
+ }
+ synchronized (mCallbackLock) {
+ if (mCallbackExecutor != null) {
+ mCallbackExecutor.execute(() -> {
+ synchronized (mCallbackLock) {
+ if (mCallback != null) {
+ mCallback.onTimeShiftCommandRequest(
+ mIAppServiceId, cmdType, parameters);
+ }
+ }
+ });
+ }
+ }
+ }
+
+ @Override
public void onSessionStateChanged(
Session session,
@TvInteractiveAppManager.InteractiveAppState int state,
@@ -1153,6 +1288,28 @@
}
@Override
+ public void onRequestCurrentVideoBounds(Session session) {
+ if (DEBUG) {
+ Log.d(TAG, "onRequestCurrentVideoBounds");
+ }
+ if (this != mSessionCallback) {
+ Log.w(TAG, "onRequestCurrentVideoBounds - session not created");
+ return;
+ }
+ synchronized (mCallbackLock) {
+ if (mCallbackExecutor != null) {
+ mCallbackExecutor.execute(() -> {
+ synchronized (mCallbackLock) {
+ if (mCallback != null) {
+ mCallback.onRequestCurrentVideoBounds(mIAppServiceId);
+ }
+ }
+ });
+ }
+ }
+ }
+
+ @Override
public void onRequestCurrentChannelUri(Session session) {
if (DEBUG) {
Log.d(TAG, "onRequestCurrentChannelUri");
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index d8705a7..5b0c2a2 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -2432,13 +2432,12 @@
throwExceptionAsNecessary(env, BAD_VALUE);
return;
}
- NativeCryptoInfo cryptoInfo = [env, cryptoInfoObj, size]{
- if (cryptoInfoObj == nullptr) {
- return NativeCryptoInfo{size};
- } else {
- return NativeCryptoInfo{env, cryptoInfoObj};
- }
- }();
+ auto cryptoInfo =
+ cryptoInfoObj ? NativeCryptoInfo{size} : NativeCryptoInfo{env, cryptoInfoObj};
+ if (env->ExceptionCheck()) {
+ // Creation of cryptoInfo failed. Let the exception bubble up.
+ return;
+ }
err = codec->queueEncryptedLinearBlock(
index,
memory,
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index da920bb..9552200 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -956,14 +956,16 @@
static void
android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
- jobject jAttributionSource)
+ jobject jAttributionSource,
+ jint jAudioSessionId)
{
ALOGV("native_setup");
Parcel* parcel = parcelForJavaObject(env, jAttributionSource);
android::content::AttributionSourceState attributionSource;
attributionSource.readFromParcel(parcel);
- sp<MediaPlayer> mp = sp<MediaPlayer>::make(attributionSource);
+ sp<MediaPlayer> mp = sp<MediaPlayer>::make(
+ attributionSource, static_cast<audio_session_t>(jAudioSessionId));
if (mp == NULL) {
jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
return;
@@ -1419,7 +1421,9 @@
{"native_setMetadataFilter", "(Landroid/os/Parcel;)I", (void *)android_media_MediaPlayer_setMetadataFilter},
{"native_getMetadata", "(ZZLandroid/os/Parcel;)Z", (void *)android_media_MediaPlayer_getMetadata},
{"native_init", "()V", (void *)android_media_MediaPlayer_native_init},
- {"native_setup", "(Ljava/lang/Object;Landroid/os/Parcel;)V",(void *)android_media_MediaPlayer_native_setup},
+ {"native_setup",
+ "(Ljava/lang/Object;Landroid/os/Parcel;I)V",
+ (void *)android_media_MediaPlayer_native_setup},
{"native_finalize", "()V", (void *)android_media_MediaPlayer_native_finalize},
{"getAudioSessionId", "()I", (void *)android_media_MediaPlayer_get_audio_session_id},
{"native_setAudioSessionId", "(I)V", (void *)android_media_MediaPlayer_set_audio_session_id},
diff --git a/media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplayProvider.java b/media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplayProvider.java
index 2cba03b..8752e3d 100644
--- a/media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplayProvider.java
+++ b/media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplayProvider.java
@@ -312,7 +312,7 @@
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
mSettingsPendingIntent = PendingIntent.getActivity(
- mContext, 0, settingsIntent, PendingIntent.FLAG_MUTABLE_UNAUDITED, null);
+ mContext, 0, settingsIntent, PendingIntent.FLAG_IMMUTABLE, null);
}
return mSettingsPendingIntent;
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerUnitTest.java
index f480566..f812d5f 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerUnitTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerUnitTest.java
@@ -23,6 +23,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -56,6 +57,7 @@
MediaPlayer mediaPlayer = new MediaPlayer(virtualDeviceContext);
assertNotEquals(vdmPlaybackSessionId, mediaPlayer.getAudioSessionId());
+ assertTrue(mediaPlayer.getAudioSessionId() > 0);
}
@Test
diff --git a/media/tests/projection/TEST_MAPPING b/media/tests/projection/TEST_MAPPING
deleted file mode 100644
index ddb68af..0000000
--- a/media/tests/projection/TEST_MAPPING
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "presubmit": [
- {
- "name": "FrameworksServicesTests",
- "options": [
- {"include-filter": "android.media.projection.mediaprojectiontests"},
- {"exclude-annotation": "android.platform.test.annotations.FlakyTest"},
- {"exclude-annotation": "androidx.test.filters.FlakyTest"},
- {"exclude-annotation": "org.junit.Ignore"}
- ]
- }
- ]
-}
diff --git a/media/tests/projection/src/android/media/projection/MediaProjectionConfigTest.java b/media/tests/projection/src/android/media/projection/MediaProjectionConfigTest.java
index a30f2e3..2820606 100644
--- a/media/tests/projection/src/android/media/projection/MediaProjectionConfigTest.java
+++ b/media/tests/projection/src/android/media/projection/MediaProjectionConfigTest.java
@@ -22,8 +22,6 @@
import static com.google.common.truth.Truth.assertThat;
-import static org.junit.Assert.assertThrows;
-
import android.os.Parcel;
import android.platform.test.annotations.Presubmit;
@@ -44,7 +42,7 @@
@RunWith(AndroidJUnit4.class)
public class MediaProjectionConfigTest {
private static final MediaProjectionConfig DISPLAY_CONFIG =
- MediaProjectionConfig.createConfigForDisplay(DEFAULT_DISPLAY);
+ MediaProjectionConfig.createConfigForDefaultDisplay();
private static final MediaProjectionConfig USERS_CHOICE_CONFIG =
MediaProjectionConfig.createConfigForUserChoice();
@@ -60,10 +58,6 @@
@Test
public void testCreateDisplayConfig() {
- assertThrows(IllegalArgumentException.class,
- () -> MediaProjectionConfig.createConfigForDisplay(-1));
- assertThrows(IllegalArgumentException.class,
- () -> MediaProjectionConfig.createConfigForDisplay(DEFAULT_DISPLAY + 1));
assertThat(DISPLAY_CONFIG.getRegionToCapture()).isEqualTo(CAPTURE_REGION_FIXED_DISPLAY);
assertThat(DISPLAY_CONFIG.getDisplayToCapture()).isEqualTo(DEFAULT_DISPLAY);
}
@@ -78,7 +72,7 @@
assertThat(MediaProjectionConfig.createConfigForUserChoice()).isEqualTo(
USERS_CHOICE_CONFIG);
assertThat(DISPLAY_CONFIG).isNotEqualTo(USERS_CHOICE_CONFIG);
- assertThat(MediaProjectionConfig.createConfigForDisplay(DEFAULT_DISPLAY)).isEqualTo(
+ assertThat(MediaProjectionConfig.createConfigForDefaultDisplay()).isEqualTo(
DISPLAY_CONFIG);
}
}
diff --git a/media/tests/projection/src/android/media/projection/MediaProjectionManagerTest.java b/media/tests/projection/src/android/media/projection/MediaProjectionManagerTest.java
index a3e4908..00ab150 100644
--- a/media/tests/projection/src/android/media/projection/MediaProjectionManagerTest.java
+++ b/media/tests/projection/src/android/media/projection/MediaProjectionManagerTest.java
@@ -17,7 +17,6 @@
package android.media.projection;
import static android.media.projection.MediaProjectionManager.EXTRA_MEDIA_PROJECTION_CONFIG;
-import static android.view.Display.DEFAULT_DISPLAY;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
@@ -59,7 +58,7 @@
private Context mContext;
private MockitoSession mMockingSession;
private static final MediaProjectionConfig DISPLAY_CONFIG =
- MediaProjectionConfig.createConfigForDisplay(DEFAULT_DISPLAY);
+ MediaProjectionConfig.createConfigForDefaultDisplay();
private static final MediaProjectionConfig USERS_CHOICE_CONFIG =
MediaProjectionConfig.createConfigForUserChoice();
diff --git a/native/android/input.cpp b/native/android/input.cpp
index 5e5ebed..f1c3088 100644
--- a/native/android/input.cpp
+++ b/native/android/input.cpp
@@ -299,6 +299,8 @@
return AMOTION_EVENT_CLASSIFICATION_TWO_FINGER_SWIPE;
case android::MotionClassification::MULTI_FINGER_SWIPE:
return AMOTION_EVENT_CLASSIFICATION_MULTI_FINGER_SWIPE;
+ case android::MotionClassification::PINCH:
+ return AMOTION_EVENT_CLASSIFICATION_PINCH;
}
}
diff --git a/native/webview/TEST_MAPPING b/native/webview/TEST_MAPPING
index bd25200..c1bc6d7 100644
--- a/native/webview/TEST_MAPPING
+++ b/native/webview/TEST_MAPPING
@@ -9,6 +9,14 @@
]
},
{
+ "name": "CtsSdkSandboxWebkitTestCases",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ },
+ {
"name": "CtsHostsideWebViewTests",
"options": [
{
diff --git a/opengl/java/android/opengl/Matrix.java b/opengl/java/android/opengl/Matrix.java
index ce3f57e..5ae341b 100644
--- a/opengl/java/android/opengl/Matrix.java
+++ b/opengl/java/android/opengl/Matrix.java
@@ -16,6 +16,8 @@
package android.opengl;
+import androidx.annotation.NonNull;
+
/**
* Matrix math utilities. These methods operate on OpenGL ES format
* matrices and vectors stored in float arrays.
@@ -38,7 +40,11 @@
public class Matrix {
/** Temporary memory for operations that need temporary matrix data. */
- private final static float[] sTemp = new float[32];
+ private static final ThreadLocal<float[]> ThreadTmp = new ThreadLocal() {
+ @Override protected float[] initialValue() {
+ return new float[32];
+ }
+ };
/**
* @deprecated All methods are static, do not instantiate this class.
@@ -46,6 +52,40 @@
@Deprecated
public Matrix() {}
+ private static boolean overlap(
+ float[] a, int aStart, int aLength, float[] b, int bStart, int bLength) {
+ if (a != b) {
+ return false;
+ }
+
+ if (aStart == bStart) {
+ return true;
+ }
+
+ int aEnd = aStart + aLength;
+ int bEnd = bStart + bLength;
+
+ if (aEnd == bEnd) {
+ return true;
+ }
+
+ if (aStart < bStart && bStart < aEnd) {
+ return true;
+ }
+ if (aStart < bEnd && bEnd < aEnd) {
+ return true;
+ }
+
+ if (bStart < aStart && aStart < bEnd) {
+ return true;
+ }
+ if (bStart < aEnd && aEnd < bEnd) {
+ return true;
+ }
+
+ return false;
+ }
+
/**
* Multiplies two 4x4 matrices together and stores the result in a third 4x4
* matrix. In matrix notation: result = lhs x rhs. Due to the way
@@ -53,9 +93,9 @@
* effect as first multiplying by the rhs matrix, then multiplying by
* the lhs matrix. This is the opposite of what you might expect.
* <p>
- * The same float array may be passed for result, lhs, and/or rhs. However,
- * the result element values are undefined if the result elements overlap
- * either the lhs or rhs elements.
+ * The same float array may be passed for result, lhs, and/or rhs. This
+ * operation is expected to do the correct thing if the result elements
+ * overlap with either of the lhs or rhs elements.
*
* @param result The float array that holds the result.
* @param resultOffset The offset into the result array where the result is
@@ -65,20 +105,101 @@
* @param rhs The float array that holds the right-hand-side matrix.
* @param rhsOffset The offset into the rhs array where the rhs is stored.
*
- * @throws IllegalArgumentException if result, lhs, or rhs are null, or if
- * resultOffset + 16 > result.length or lhsOffset + 16 > lhs.length or
- * rhsOffset + 16 > rhs.length.
+ * @throws IllegalArgumentException under any of the following conditions:
+ * result, lhs, or rhs are null;
+ * resultOffset + 16 > result.length
+ * or lhsOffset + 16 > lhs.length
+ * or rhsOffset + 16 > rhs.length;
+ * resultOffset < 0 or lhsOffset < 0 or rhsOffset < 0
*/
- public static native void multiplyMM(float[] result, int resultOffset,
- float[] lhs, int lhsOffset, float[] rhs, int rhsOffset);
+ public static void multiplyMM(float[] result, int resultOffset,
+ float[] lhs, int lhsOffset, float[] rhs, int rhsOffset) {
+ // error checking
+ if (result == null) {
+ throw new IllegalArgumentException("result == null");
+ }
+ if (lhs == null) {
+ throw new IllegalArgumentException("lhs == null");
+ }
+ if (rhs == null) {
+ throw new IllegalArgumentException("rhs == null");
+ }
+ if (resultOffset < 0) {
+ throw new IllegalArgumentException("resultOffset < 0");
+ }
+ if (lhsOffset < 0) {
+ throw new IllegalArgumentException("lhsOffset < 0");
+ }
+ if (rhsOffset < 0) {
+ throw new IllegalArgumentException("rhsOffset < 0");
+ }
+ if (result.length < resultOffset + 16) {
+ throw new IllegalArgumentException("result.length < resultOffset + 16");
+ }
+ if (lhs.length < lhsOffset + 16) {
+ throw new IllegalArgumentException("lhs.length < lhsOffset + 16");
+ }
+ if (rhs.length < rhsOffset + 16) {
+ throw new IllegalArgumentException("rhs.length < rhsOffset + 16");
+ }
+
+ // Check for overlap between rhs and result or lhs and result
+ if ( overlap(result, resultOffset, 16, lhs, lhsOffset, 16)
+ || overlap(result, resultOffset, 16, rhs, rhsOffset, 16) ) {
+ float[] tmp = ThreadTmp.get();
+ for (int i=0; i<4; i++) {
+ final float rhs_i0 = rhs[ 4*i + 0 + rhsOffset ];
+ float ri0 = lhs[ 0 + lhsOffset ] * rhs_i0;
+ float ri1 = lhs[ 1 + lhsOffset ] * rhs_i0;
+ float ri2 = lhs[ 2 + lhsOffset ] * rhs_i0;
+ float ri3 = lhs[ 3 + lhsOffset ] * rhs_i0;
+ for (int j=1; j<4; j++) {
+ final float rhs_ij = rhs[ 4*i + j + rhsOffset];
+ ri0 += lhs[ 4*j + 0 + lhsOffset ] * rhs_ij;
+ ri1 += lhs[ 4*j + 1 + lhsOffset ] * rhs_ij;
+ ri2 += lhs[ 4*j + 2 + lhsOffset ] * rhs_ij;
+ ri3 += lhs[ 4*j + 3 + lhsOffset ] * rhs_ij;
+ }
+ tmp[ 4*i + 0 ] = ri0;
+ tmp[ 4*i + 1 ] = ri1;
+ tmp[ 4*i + 2 ] = ri2;
+ tmp[ 4*i + 3 ] = ri3;
+ }
+
+ // copy from tmp to result
+ for (int i=0; i < 16; i++) {
+ result[ i + resultOffset ] = tmp[ i ];
+ }
+
+ } else {
+ for (int i=0; i<4; i++) {
+ final float rhs_i0 = rhs[ 4*i + 0 + rhsOffset ];
+ float ri0 = lhs[ 0 + lhsOffset ] * rhs_i0;
+ float ri1 = lhs[ 1 + lhsOffset ] * rhs_i0;
+ float ri2 = lhs[ 2 + lhsOffset ] * rhs_i0;
+ float ri3 = lhs[ 3 + lhsOffset ] * rhs_i0;
+ for (int j=1; j<4; j++) {
+ final float rhs_ij = rhs[ 4*i + j + rhsOffset];
+ ri0 += lhs[ 4*j + 0 + lhsOffset ] * rhs_ij;
+ ri1 += lhs[ 4*j + 1 + lhsOffset ] * rhs_ij;
+ ri2 += lhs[ 4*j + 2 + lhsOffset ] * rhs_ij;
+ ri3 += lhs[ 4*j + 3 + lhsOffset ] * rhs_ij;
+ }
+ result[ 4*i + 0 + resultOffset ] = ri0;
+ result[ 4*i + 1 + resultOffset ] = ri1;
+ result[ 4*i + 2 + resultOffset ] = ri2;
+ result[ 4*i + 3 + resultOffset ] = ri3;
+ }
+ }
+ }
/**
* Multiplies a 4 element vector by a 4x4 matrix and stores the result in a
* 4-element column vector. In matrix notation: result = lhs x rhs
* <p>
* The same float array may be passed for resultVec, lhsMat, and/or rhsVec.
- * However, the resultVec element values are undefined if the resultVec
- * elements overlap either the lhsMat or rhsVec elements.
+ * This operation is expected to do the correct thing if the result elements
+ * overlap with either of the lhs or rhs elements.
*
* @param resultVec The float array that holds the result vector.
* @param resultVecOffset The offset into the result array where the result
@@ -89,14 +210,67 @@
* @param rhsVecOffset The offset into the rhs vector where the rhs vector
* is stored.
*
- * @throws IllegalArgumentException if resultVec, lhsMat,
- * or rhsVec are null, or if resultVecOffset + 4 > resultVec.length
- * or lhsMatOffset + 16 > lhsMat.length or
- * rhsVecOffset + 4 > rhsVec.length.
+ * @throws IllegalArgumentException under any of the following conditions:
+ * resultVec, lhsMat, or rhsVec are null;
+ * resultVecOffset + 4 > resultVec.length
+ * or lhsMatOffset + 16 > lhsMat.length
+ * or rhsVecOffset + 4 > rhsVec.length;
+ * resultVecOffset < 0 or lhsMatOffset < 0 or rhsVecOffset < 0
*/
- public static native void multiplyMV(float[] resultVec,
+ public static void multiplyMV(float[] resultVec,
int resultVecOffset, float[] lhsMat, int lhsMatOffset,
- float[] rhsVec, int rhsVecOffset);
+ float[] rhsVec, int rhsVecOffset) {
+ // error checking
+ if (resultVec == null) {
+ throw new IllegalArgumentException("resultVec == null");
+ }
+ if (lhsMat == null) {
+ throw new IllegalArgumentException("lhsMat == null");
+ }
+ if (rhsVec == null) {
+ throw new IllegalArgumentException("rhsVec == null");
+ }
+ if (resultVecOffset < 0) {
+ throw new IllegalArgumentException("resultVecOffset < 0");
+ }
+ if (lhsMatOffset < 0) {
+ throw new IllegalArgumentException("lhsMatOffset < 0");
+ }
+ if (rhsVecOffset < 0) {
+ throw new IllegalArgumentException("rhsVecOffset < 0");
+ }
+ if (resultVec.length < resultVecOffset + 4) {
+ throw new IllegalArgumentException("resultVec.length < resultVecOffset + 4");
+ }
+ if (lhsMat.length < lhsMatOffset + 16) {
+ throw new IllegalArgumentException("lhsMat.length < lhsMatOffset + 16");
+ }
+ if (rhsVec.length < rhsVecOffset + 4) {
+ throw new IllegalArgumentException("rhsVec.length < rhsVecOffset + 4");
+ }
+
+ float tmp0 = lhsMat[0 + 4 * 0 + lhsMatOffset] * rhsVec[0 + rhsVecOffset] +
+ lhsMat[0 + 4 * 1 + lhsMatOffset] * rhsVec[1 + rhsVecOffset] +
+ lhsMat[0 + 4 * 2 + lhsMatOffset] * rhsVec[2 + rhsVecOffset] +
+ lhsMat[0 + 4 * 3 + lhsMatOffset] * rhsVec[3 + rhsVecOffset];
+ float tmp1 = lhsMat[1 + 4 * 0 + lhsMatOffset] * rhsVec[0 + rhsVecOffset] +
+ lhsMat[1 + 4 * 1 + lhsMatOffset] * rhsVec[1 + rhsVecOffset] +
+ lhsMat[1 + 4 * 2 + lhsMatOffset] * rhsVec[2 + rhsVecOffset] +
+ lhsMat[1 + 4 * 3 + lhsMatOffset] * rhsVec[3 + rhsVecOffset];
+ float tmp2 = lhsMat[2 + 4 * 0 + lhsMatOffset] * rhsVec[0 + rhsVecOffset] +
+ lhsMat[2 + 4 * 1 + lhsMatOffset] * rhsVec[1 + rhsVecOffset] +
+ lhsMat[2 + 4 * 2 + lhsMatOffset] * rhsVec[2 + rhsVecOffset] +
+ lhsMat[2 + 4 * 3 + lhsMatOffset] * rhsVec[3 + rhsVecOffset];
+ float tmp3 = lhsMat[3 + 4 * 0 + lhsMatOffset] * rhsVec[0 + rhsVecOffset] +
+ lhsMat[3 + 4 * 1 + lhsMatOffset] * rhsVec[1 + rhsVecOffset] +
+ lhsMat[3 + 4 * 2 + lhsMatOffset] * rhsVec[2 + rhsVecOffset] +
+ lhsMat[3 + 4 * 3 + lhsMatOffset] * rhsVec[3 + rhsVecOffset];
+
+ resultVec[ 0 + resultVecOffset ] = tmp0;
+ resultVec[ 1 + resultVecOffset ] = tmp1;
+ resultVec[ 2 + resultVecOffset ] = tmp2;
+ resultVec[ 3 + resultVecOffset ] = tmp3;
+ }
/**
* Transposes a 4 x 4 matrix.
@@ -537,10 +711,9 @@
public static void rotateM(float[] rm, int rmOffset,
float[] m, int mOffset,
float a, float x, float y, float z) {
- synchronized(sTemp) {
- setRotateM(sTemp, 0, a, x, y, z);
- multiplyMM(rm, rmOffset, m, mOffset, sTemp, 0);
- }
+ float[] tmp = ThreadTmp.get();
+ setRotateM(tmp, 16, a, x, y, z);
+ multiplyMM(rm, rmOffset, m, mOffset, tmp, 16);
}
/**
@@ -556,11 +729,7 @@
*/
public static void rotateM(float[] m, int mOffset,
float a, float x, float y, float z) {
- synchronized(sTemp) {
- setRotateM(sTemp, 0, a, x, y, z);
- multiplyMM(sTemp, 16, m, mOffset, sTemp, 0);
- System.arraycopy(sTemp, 16, m, mOffset, 16);
- }
+ rotateM(m, mOffset, m, mOffset, a, x, y, z);
}
/**
@@ -640,9 +809,14 @@
* @param rm returns the result
* @param rmOffset index into rm where the result matrix starts
* @param x angle of rotation, in degrees
- * @param y angle of rotation, in degrees
+ * @param y is broken, do not use
* @param z angle of rotation, in degrees
+ *
+ * @deprecated This method is incorrect around the y axis. This method is
+ * deprecated and replaced (below) by setRotateEulerM2 which
+ * behaves correctly
*/
+ @Deprecated
public static void setRotateEulerM(float[] rm, int rmOffset,
float x, float y, float z) {
x *= (float) (Math.PI / 180.0f);
@@ -679,6 +853,64 @@
}
/**
+ * Converts Euler angles to a rotation matrix.
+ *
+ * @param rm returns the result
+ * @param rmOffset index into rm where the result matrix starts
+ * @param x angle of rotation, in degrees
+ * @param y angle of rotation, in degrees
+ * @param z angle of rotation, in degrees
+ *
+ * @throws IllegalArgumentException if rm is null;
+ * or if rmOffset + 16 > rm.length;
+ * rmOffset < 0
+ */
+ public static void setRotateEulerM2(@NonNull float[] rm, int rmOffset,
+ float x, float y, float z) {
+ if (rm == null) {
+ throw new IllegalArgumentException("rm == null");
+ }
+ if (rmOffset < 0) {
+ throw new IllegalArgumentException("rmOffset < 0");
+ }
+ if (rm.length < rmOffset + 16) {
+ throw new IllegalArgumentException("rm.length < rmOffset + 16");
+ }
+
+ x *= (float) (Math.PI / 180.0f);
+ y *= (float) (Math.PI / 180.0f);
+ z *= (float) (Math.PI / 180.0f);
+ float cx = (float) Math.cos(x);
+ float sx = (float) Math.sin(x);
+ float cy = (float) Math.cos(y);
+ float sy = (float) Math.sin(y);
+ float cz = (float) Math.cos(z);
+ float sz = (float) Math.sin(z);
+ float cxsy = cx * sy;
+ float sxsy = sx * sy;
+
+ rm[rmOffset + 0] = cy * cz;
+ rm[rmOffset + 1] = -cy * sz;
+ rm[rmOffset + 2] = sy;
+ rm[rmOffset + 3] = 0.0f;
+
+ rm[rmOffset + 4] = sxsy * cz + cx * sz;
+ rm[rmOffset + 5] = -sxsy * sz + cx * cz;
+ rm[rmOffset + 6] = -sx * cy;
+ rm[rmOffset + 7] = 0.0f;
+
+ rm[rmOffset + 8] = -cxsy * cz + sx * sz;
+ rm[rmOffset + 9] = cxsy * sz + sx * cz;
+ rm[rmOffset + 10] = cx * cy;
+ rm[rmOffset + 11] = 0.0f;
+
+ rm[rmOffset + 12] = 0.0f;
+ rm[rmOffset + 13] = 0.0f;
+ rm[rmOffset + 14] = 0.0f;
+ rm[rmOffset + 15] = 1.0f;
+ }
+
+ /**
* Defines a viewing transformation in terms of an eye point, a center of
* view, and an up vector.
*
diff --git a/packages/CarrierDefaultApp/res/values/strings.xml b/packages/CarrierDefaultApp/res/values/strings.xml
index df4705b..6e2927d 100644
--- a/packages/CarrierDefaultApp/res/values/strings.xml
+++ b/packages/CarrierDefaultApp/res/values/strings.xml
@@ -17,9 +17,9 @@
<!-- Telephony notification channel name for performance boost notifications. -->
<string name="performance_boost_notification_channel">Performance boost</string>
<!-- Notification title text for the performance boost notification. -->
- <string name="performance_boost_notification_title">%s recommends a performance boost</string>
+ <string name="performance_boost_notification_title">Improve your 5G experience</string>
<!-- Notification detail text for the performance boost notification. -->
- <string name="performance_boost_notification_detail">Buy a performance boost for better network performance</string>
+ <string name="performance_boost_notification_detail">%1$s recommends buying a performance boost plan. Tap to buy through %2$s.</string>
<!-- Notification button text to cancel the performance boost notification. -->
<string name="performance_boost_notification_button_not_now">Not now</string>
<!-- Notification button text to manage the performance boost notification. -->
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiver.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiver.java
index 1b02c2b..d4ce5f5 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiver.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiver.java
@@ -178,9 +178,9 @@
return false;
}
- String appName = intent.getStringExtra(SlicePurchaseController.EXTRA_REQUESTING_APP_NAME);
- if (TextUtils.isEmpty(appName)) {
- loge("isIntentValid: empty requesting application name: " + appName);
+ String carrier = intent.getStringExtra(SlicePurchaseController.EXTRA_CARRIER);
+ if (TextUtils.isEmpty(carrier)) {
+ loge("isIntentValid: empty carrier: " + carrier);
return false;
}
@@ -310,14 +310,14 @@
channel.setBlockable(true);
context.getSystemService(NotificationManager.class).createNotificationChannel(channel);
+ String carrier = intent.getStringExtra(SlicePurchaseController.EXTRA_CARRIER);
+
Notification notification =
new Notification.Builder(context, PERFORMANCE_BOOST_NOTIFICATION_CHANNEL_ID)
- .setContentTitle(String.format(res.getString(
- R.string.performance_boost_notification_title),
- intent.getStringExtra(
- SlicePurchaseController.EXTRA_REQUESTING_APP_NAME)))
- .setContentText(res.getString(
- R.string.performance_boost_notification_detail))
+ .setContentTitle(res.getString(
+ R.string.performance_boost_notification_title))
+ .setContentText(String.format(res.getString(
+ R.string.performance_boost_notification_detail), carrier, carrier))
.setSmallIcon(R.drawable.ic_performance_boost)
.setContentIntent(createContentIntent(context, intent, 1))
.setDeleteIntent(intent.getParcelableExtra(
diff --git a/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/SlicePurchaseActivityTest.java b/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/SlicePurchaseActivityTest.java
index 1bf644e..daf0b42 100644
--- a/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/SlicePurchaseActivityTest.java
+++ b/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/SlicePurchaseActivityTest.java
@@ -48,7 +48,7 @@
@RunWith(AndroidJUnit4.class)
public class SlicePurchaseActivityTest extends ActivityUnitTestCase<SlicePurchaseActivity> {
- private static final String TAG = "SlicePurchaseActivityTest";
+ private static final String CARRIER = "Some Carrier";
private static final String URL = "file:///android_asset/slice_purchase_test.html";
private static final int PHONE_ID = 0;
@@ -95,7 +95,7 @@
TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY);
intent.putExtra(SlicePurchaseController.EXTRA_PURCHASE_URL,
SlicePurchaseController.SLICE_PURCHASE_TEST_FILE);
- intent.putExtra(SlicePurchaseController.EXTRA_REQUESTING_APP_NAME, TAG);
+ intent.putExtra(SlicePurchaseController.EXTRA_CARRIER, CARRIER);
Intent spiedIntent = spy(intent);
// set up pending intents
diff --git a/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiverTest.java b/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiverTest.java
index 568d63c..952789c 100644
--- a/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiverTest.java
+++ b/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiverTest.java
@@ -62,7 +62,7 @@
@RunWith(AndroidJUnit4.class)
public class SlicePurchaseBroadcastReceiverTest {
private static final int PHONE_ID = 0;
- private static final String TAG = "SlicePurchaseBroadcastReceiverTest";
+ private static final String CARRIER = "Some Carrier";
private static final String EXTRA = "EXTRA";
@Mock Intent mIntent;
@@ -136,8 +136,7 @@
eq(SlicePurchaseController.EXTRA_PREMIUM_CAPABILITY), anyInt());
doReturn(SlicePurchaseController.SLICE_PURCHASE_TEST_FILE).when(mIntent).getStringExtra(
eq(SlicePurchaseController.EXTRA_PURCHASE_URL));
- doReturn(TAG).when(mIntent).getStringExtra(
- eq(SlicePurchaseController.EXTRA_REQUESTING_APP_NAME));
+ doReturn(CARRIER).when(mIntent).getStringExtra(eq(SlicePurchaseController.EXTRA_CARRIER));
assertFalse(SlicePurchaseBroadcastReceiver.isIntentValid(mIntent));
// set up pending intent
@@ -229,8 +228,7 @@
eq(SlicePurchaseController.EXTRA_PREMIUM_CAPABILITY), anyInt());
doReturn(SlicePurchaseController.SLICE_PURCHASE_TEST_FILE).when(mIntent).getStringExtra(
eq(SlicePurchaseController.EXTRA_PURCHASE_URL));
- doReturn(TAG).when(mIntent).getStringExtra(
- eq(SlicePurchaseController.EXTRA_REQUESTING_APP_NAME));
+ doReturn(CARRIER).when(mIntent).getStringExtra(eq(SlicePurchaseController.EXTRA_CARRIER));
mSlicePurchaseBroadcastReceiver.onReceive(mContext, mIntent);
}
diff --git a/packages/CredentialManager/Android.bp b/packages/CredentialManager/Android.bp
index 90bb2d1..2cb3468 100644
--- a/packages/CredentialManager/Android.bp
+++ b/packages/CredentialManager/Android.bp
@@ -40,6 +40,7 @@
],
platform_apis: true,
+ privileged: true,
kotlincflags: ["-Xjvm-default=enable"],
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
index 1e5bd7b..7d43364 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
@@ -152,22 +152,6 @@
return CreateFlowUtils.toRequestDisplayInfo(requestInfo, context)
}
- companion object {
- // TODO: find a way to resolve this static field leak problem
- lateinit var repo: CredentialManagerRepo
-
- fun setup(
- context: Context,
- intent: Intent,
- ) {
- repo = CredentialManagerRepo(context, intent)
- }
-
- fun getInstance(): CredentialManagerRepo {
- return repo
- }
- }
-
// TODO: below are prototype functionalities. To be removed for productionization.
private fun testCreateCredentialEnabledProviderList(): List<CreateCredentialProviderData> {
return listOf(
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt
index 686415f..0620f9a 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt
@@ -45,19 +45,19 @@
class CredentialSelectorActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- CredentialManagerRepo.setup(this, intent)
+ val credManRepo = CredentialManagerRepo(this, intent)
UserConfigRepo.setup(this)
- val requestInfo = CredentialManagerRepo.getInstance().requestInfo
+ val requestInfo = credManRepo.requestInfo
setContent {
CredentialSelectorTheme {
- CredentialManagerBottomSheet(DialogType.toDialogType(requestInfo.type))
+ CredentialManagerBottomSheet(DialogType.toDialogType(requestInfo.type), credManRepo)
}
}
}
@ExperimentalMaterialApi
@Composable
- fun CredentialManagerBottomSheet(dialogType: DialogType) {
+ fun CredentialManagerBottomSheet(dialogType: DialogType, credManRepo: CredentialManagerRepo) {
val providerActivityResult = remember { mutableStateOf<ProviderActivityResult?>(null) }
val launcher = rememberLauncherForActivityResult(
ActivityResultContracts.StartIntentSenderForResult()
@@ -66,7 +66,9 @@
}
when (dialogType) {
DialogType.CREATE_PASSKEY -> {
- val viewModel: CreateCredentialViewModel = viewModel()
+ val viewModel: CreateCredentialViewModel = viewModel{
+ CreateCredentialViewModel(credManRepo)
+ }
lifecycleScope.launch {
viewModel.observeDialogResult().collect{ dialogResult ->
onCancel(dialogResult)
@@ -79,7 +81,9 @@
CreateCredentialScreen(viewModel = viewModel, providerActivityLauncher = launcher)
}
DialogType.GET_CREDENTIALS -> {
- val viewModel: GetCredentialViewModel = viewModel()
+ val viewModel: GetCredentialViewModel = viewModel{
+ GetCredentialViewModel(credManRepo)
+ }
lifecycleScope.launch {
viewModel.observeDialogResult().collect{ dialogResult ->
onCancel(dialogResult)
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt b/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
index 9803fc6..09f9b5e 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
@@ -44,6 +44,7 @@
import com.android.credentialmanager.jetpack.developer.CreatePublicKeyCredentialRequest
import com.android.credentialmanager.jetpack.developer.PublicKeyCredential.Companion.TYPE_PUBLIC_KEY_CREDENTIAL
import com.android.credentialmanager.jetpack.provider.Action
+import com.android.credentialmanager.jetpack.provider.AuthenticationAction
import com.android.credentialmanager.jetpack.provider.CredentialCountInformation
import com.android.credentialmanager.jetpack.provider.CredentialEntry
import com.android.credentialmanager.jetpack.provider.CreateEntry
@@ -140,16 +141,20 @@
providerIcon: Drawable,
authEntry: Entry?,
): AuthenticationEntryInfo? {
- // TODO: should also call fromSlice after getting the official jetpack code.
-
if (authEntry == null) {
return null
}
+ val authStructuredEntry = AuthenticationAction.fromSlice(
+ authEntry!!.slice)
+ if (authStructuredEntry == null) {
+ return null
+ }
+
return AuthenticationEntryInfo(
providerId = providerId,
entryKey = authEntry.key,
entrySubkey = authEntry.subkey,
- pendingIntent = authEntry.pendingIntent,
+ pendingIntent = authStructuredEntry.pendingIntent,
fillInIntent = authEntry.frameworkExtrasIntent,
title = providerDisplayName,
icon = providerIcon,
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialViewModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialViewModel.kt
index 3e1137d..ac84503 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialViewModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialViewModel.kt
@@ -52,10 +52,9 @@
)
class CreateCredentialViewModel(
- credManRepo: CredentialManagerRepo = CredentialManagerRepo.getInstance(),
- userConfigRepo: UserConfigRepo = UserConfigRepo.getInstance()
+ private val credManRepo: CredentialManagerRepo,
+ userConfigRepo: UserConfigRepo = UserConfigRepo.getInstance(),
) : ViewModel() {
-
var providerEnableListUiState = credManRepo.getCreateProviderEnableListInitialUiState()
var providerDisableListUiState = credManRepo.getCreateProviderDisableListInitialUiState()
@@ -142,12 +141,12 @@
}
fun onDisabledProvidersSelected() {
- CredentialManagerRepo.getInstance().onCancel()
+ credManRepo.onCancel()
dialogResult.tryEmit(DialogResult(ResultState.LAUNCH_SETTING_CANCELED))
}
fun onCancel() {
- CredentialManagerRepo.getInstance().onCancel()
+ credManRepo.onCancel()
dialogResult.tryEmit(DialogResult(ResultState.NORMAL_CANCELED))
}
@@ -189,7 +188,7 @@
hidden = true,
)
} else {
- CredentialManagerRepo.getInstance().onOptionSelected(
+ credManRepo.onOptionSelected(
providerId,
entryKey,
entrySubkey
@@ -243,7 +242,7 @@
"$providerId, key=${entry.entryKey}, subkey=${entry.entrySubkey}, " +
"resultCode=$resultCode, resultData=$resultData}"
)
- CredentialManagerRepo.getInstance().onOptionSelected(
+ credManRepo.onOptionSelected(
providerId, entry.entryKey, entry.entrySubkey, resultCode, resultData,
)
} else {
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialViewModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialViewModel.kt
index af59a0a..6f0f76b 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialViewModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialViewModel.kt
@@ -46,9 +46,7 @@
val isNoAccount: Boolean = false,
)
-class GetCredentialViewModel(
- credManRepo: CredentialManagerRepo = CredentialManagerRepo.getInstance()
-) : ViewModel() {
+class GetCredentialViewModel(private val credManRepo: CredentialManagerRepo) : ViewModel() {
var uiState by mutableStateOf(credManRepo.getCredentialInitialUiState())
private set
@@ -70,9 +68,7 @@
hidden = true,
)
} else {
- CredentialManagerRepo.getInstance().onOptionSelected(
- entry.providerId, entry.entryKey, entry.entrySubkey,
- )
+ credManRepo.onOptionSelected(entry.providerId, entry.entryKey, entry.entrySubkey)
dialogResult.tryEmit(DialogResult(ResultState.COMPLETE))
}
}
@@ -110,7 +106,7 @@
"${entry.providerId}, key=${entry.entryKey}, subkey=${entry.entrySubkey}, " +
"resultCode=$resultCode, resultData=$resultData}"
)
- CredentialManagerRepo.getInstance().onOptionSelected(
+ credManRepo.onOptionSelected(
entry.providerId, entry.entryKey, entry.entrySubkey,
resultCode, resultData,
)
@@ -144,7 +140,7 @@
}
fun onCancel() {
- CredentialManagerRepo.getInstance().onCancel()
+ credManRepo.onCancel()
dialogResult.tryEmit(DialogResult(ResultState.NORMAL_CANCELED))
}
}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/provider/AuthenticationAction.kt b/packages/CredentialManager/src/com/android/credentialmanager/jetpack/provider/AuthenticationAction.kt
new file mode 100644
index 0000000..283c7ba
--- /dev/null
+++ b/packages/CredentialManager/src/com/android/credentialmanager/jetpack/provider/AuthenticationAction.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.credentialmanager.jetpack.provider
+
+import android.app.PendingIntent
+import android.app.slice.Slice
+import android.util.Log
+import androidx.annotation.VisibleForTesting
+
+/**
+ * UI representation for a credential entry used during the get credential flow.
+ *
+ * TODO: move to jetpack.
+ */
+class AuthenticationAction constructor(
+ val pendingIntent: PendingIntent
+) {
+
+
+ companion object {
+ private const val TAG = "AuthenticationAction"
+ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+ internal const val SLICE_HINT_PENDING_INTENT =
+ "androidx.credentials.provider.authenticationAction.SLICE_HINT_PENDING_INTENT"
+
+ @JvmStatic
+ fun fromSlice(slice: Slice): AuthenticationAction? {
+ slice.items.forEach {
+ if (it.hasHint(SLICE_HINT_PENDING_INTENT)) {
+ return try {
+ AuthenticationAction(it.action)
+ } catch (e: Exception) {
+ Log.i(TAG, "fromSlice failed with: " + e.message)
+ null
+ }
+ }
+ }
+ return null
+ }
+ }
+}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/wear/PackageInstallerImpl.java b/packages/PackageInstaller/src/com/android/packageinstaller/wear/PackageInstallerImpl.java
index 8dd691d..1e37f15 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/wear/PackageInstallerImpl.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/wear/PackageInstallerImpl.java
@@ -268,7 +268,7 @@
Context.RECEIVER_EXPORTED);
// Create a matching PendingIntent and use it to generate the IntentSender
- Intent broadcastIntent = new Intent(action);
+ Intent broadcastIntent = new Intent(action).setPackage(mContext.getPackageName());
PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, packageName.hashCode(),
broadcastIntent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT
| PendingIntent.FLAG_MUTABLE);
diff --git a/packages/SettingsLib/HelpUtils/Android.bp b/packages/SettingsLib/HelpUtils/Android.bp
index aea51b1..3ec4366a 100644
--- a/packages/SettingsLib/HelpUtils/Android.bp
+++ b/packages/SettingsLib/HelpUtils/Android.bp
@@ -22,5 +22,6 @@
apex_available: [
"//apex_available:platform",
"com.android.permission",
+ "com.android.healthconnect",
],
}
diff --git a/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java b/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java
index 468a976..1592094 100644
--- a/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java
+++ b/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java
@@ -59,6 +59,18 @@
private Uri mImageUri;
private Drawable mImageDrawable;
private View mMiddleGroundView;
+ private OnBindListener mOnBindListener;
+
+ /**
+ * Interface to listen in on when {@link #onBindViewHolder(PreferenceViewHolder)} occurs.
+ */
+ public interface OnBindListener {
+ /**
+ * Called when when {@link #onBindViewHolder(PreferenceViewHolder)} occurs.
+ * @param animationView the animation view for this preference.
+ */
+ void onBind(LottieAnimationView animationView);
+ }
private final Animatable2.AnimationCallback mAnimationCallback =
new Animatable2.AnimationCallback() {
@@ -133,6 +145,17 @@
if (IS_ENABLED_LOTTIE_ADAPTIVE_COLOR) {
ColorUtils.applyDynamicColors(getContext(), illustrationView);
}
+
+ if (mOnBindListener != null) {
+ mOnBindListener.onBind(illustrationView);
+ }
+ }
+
+ /**
+ * Sets a listener to be notified when the views are binded.
+ */
+ public void setOnBindListener(OnBindListener listener) {
+ mOnBindListener = listener;
}
/**
diff --git a/packages/SettingsLib/SpaPrivileged/AndroidManifest.xml b/packages/SettingsLib/SpaPrivileged/AndroidManifest.xml
index 2efa107..d1dceb3 100644
--- a/packages/SettingsLib/SpaPrivileged/AndroidManifest.xml
+++ b/packages/SettingsLib/SpaPrivileged/AndroidManifest.xml
@@ -15,4 +15,8 @@
limitations under the License.
-->
-<manifest package="com.android.settingslib.spaprivileged" />
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.settingslib.spaprivileged">
+<uses-permission android:name="android.permission.MANAGE_USERS" />
+</manifest>
+
diff --git a/packages/SettingsLib/SpaPrivileged/res/values/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values/strings.xml
index 25dbe00..e1e7649 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values/strings.xml
@@ -27,4 +27,6 @@
<string name="app_permission_summary_not_allowed">Not allowed</string>
<!-- Manage applications, version string displayed in app snippet -->
<string name="version_text">version <xliff:g id="version_num">%1$s</xliff:g></string>
+ <!-- Label of an app on App Info page of Cloned Apps menu [CHAR LIMIT=40] -->
+ <string name="cloned_app_info_label"><xliff:g id="package_label">%1$s</xliff:g> clone</string>
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppRepository.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppRepository.kt
index 90710db..18b20733 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppRepository.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppRepository.kt
@@ -19,9 +19,11 @@
import android.content.Context
import android.content.pm.ApplicationInfo
import android.graphics.drawable.Drawable
+import android.os.UserManager
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.produceState
+import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import com.android.settingslib.Utils
import com.android.settingslib.spa.framework.compose.rememberContext
@@ -36,12 +38,24 @@
fun loadLabel(app: ApplicationInfo): String
@Composable
- fun produceLabel(app: ApplicationInfo) =
- produceState(initialValue = stringResource(R.string.summary_placeholder), app) {
+ fun produceLabel(app: ApplicationInfo, isClonedAppPage: Boolean = false): State<String> {
+ val context = LocalContext.current
+ return produceState(initialValue = stringResource(R.string.summary_placeholder), app) {
withContext(Dispatchers.IO) {
- value = loadLabel(app)
+ if (isClonedAppPage || isCloneApp(context, app)) {
+ value = context.getString(R.string.cloned_app_info_label, loadLabel(app))
+ } else {
+ value = loadLabel(app)
+ }
}
}
+ }
+
+ private fun isCloneApp(context: Context, app: ApplicationInfo): Boolean {
+ val userManager = context.getSystemService(UserManager::class.java)!!
+ val userInfo = userManager.getUserInfo(app.userId)
+ return userInfo != null && userInfo.isCloneProfile
+ }
@Composable
fun produceIcon(app: ApplicationInfo): State<Drawable?>
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt
index 16ca70f..602df54 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt
@@ -43,7 +43,7 @@
class AppInfoProvider(private val packageInfo: PackageInfo) {
@Composable
- fun AppInfo(displayVersion: Boolean = false) {
+ fun AppInfo(displayVersion: Boolean = false, isClonedAppPage: Boolean = false) {
Column(
modifier = Modifier
.fillMaxWidth()
@@ -57,7 +57,7 @@
Box(modifier = Modifier.padding(SettingsDimension.itemPaddingAround)) {
AppIcon(app = app, size = SettingsDimension.appIconInfoSize)
}
- AppLabel(app)
+ AppLabel(app, isClonedAppPage)
InstallType(app)
if (displayVersion) AppVersion()
}
@@ -99,7 +99,7 @@
}
@Composable
-internal fun AppLabel(app: ApplicationInfo) {
+internal fun AppLabel(app: ApplicationInfo, isClonedAppPage: Boolean = false) {
val appRepository = rememberAppRepository()
- SettingsTitle(title = appRepository.produceLabel(app), useMediumWeight = true)
+ SettingsTitle(title = appRepository.produceLabel(app, isClonedAppPage), useMediumWeight = true)
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothBroadcastUtils.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothBroadcastUtils.java
index 1f72609..a80061e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothBroadcastUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothBroadcastUtils.java
@@ -53,8 +53,8 @@
static final String PREFIX_BT_SYNC_INTERVAL = "SI:";
static final String PREFIX_BT_IS_ENCRYPTED = "E:";
static final String PREFIX_BT_BROADCAST_CODE = "C:";
- static final String PREFIX_BT_PRESENTATION_DELAY = "D:";
- static final String PREFIX_BT_SUBGROUPS = "G:";
+ static final String PREFIX_BT_PRESENTATION_DELAY = "PD:";
+ static final String PREFIX_BT_SUBGROUPS = "SG:";
static final String PREFIX_BT_ANDROID_VERSION = "V:";
// BluetoothLeBroadcastSubgroup
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastMetadata.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastMetadata.java
index aff9a6e..c61ebc0 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastMetadata.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastMetadata.java
@@ -28,7 +28,9 @@
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -38,6 +40,43 @@
private static final String METADATA_START = "<";
private static final String METADATA_END = ">";
private static final String PATTERN_REGEX = "<(.*?)>";
+ private static final String PATTERN_BT_BROADCAST_METADATA =
+ "T:<(.*?)>;+D:<(.*?)>;+AS:<(.*?)>;+B:<(.*?)>;+SI:<(.*?)>;+E:<(.*?)>;+C:<(.*?)>;"
+ + "+PD:<(.*?)>;+SG:(.*)";
+ private static final String PATTERN_BT_SUBGROUP =
+ "CID:<(.*?)>;+CC:<(.*?);>;+AC:<(.*?);>;+CP:<(.*?)>;+BC:<(.*)>;>;";
+ private static final String PATTERN_BT_CHANNEL = "CI:<(.*?)>;+BCCM:<(.*?);>;";
+
+ /* Index for BluetoothLeBroadcastMetadata */
+ private static int MATCH_INDEX_ADDRESS_TYPE = 1;
+ private static int MATCH_INDEX_DEVICE = 2;
+ private static int MATCH_INDEX_ADVERTISING_SID = 3;
+ private static int MATCH_INDEX_BROADCAST_ID = 4;
+ private static int MATCH_INDEX_SYNC_INTERVAL = 5;
+ private static int MATCH_INDEX_IS_ENCRYPTED = 6;
+ private static int MATCH_INDEX_BROADCAST_CODE = 7;
+ private static int MATCH_INDEX_PRESENTATION_DELAY = 8;
+ private static int MATCH_INDEX_SUBGROUPS = 9;
+
+ /* Index for BluetoothLeBroadcastSubgroup */
+ private static int MATCH_INDEX_CODEC_ID = 1;
+ private static int MATCH_INDEX_CODEC_CONFIG = 2;
+ private static int MATCH_INDEX_AUDIO_CONTENT = 3;
+ private static int MATCH_INDEX_CHANNEL_PREF = 4;
+ private static int MATCH_INDEX_BROADCAST_CHANNEL = 5;
+
+ /* Index for BluetoothLeAudioCodecConfigMetadata */
+ private static int LIST_INDEX_AUDIO_LOCATION = 0;
+ private static int LIST_INDEX_CODEC_CONFIG_RAW_METADATA = 1;
+
+ /* Index for BluetoothLeAudioContentMetadata */
+ private static int LIST_INDEX_PROGRAM_INFO = 0;
+ private static int LIST_INDEX_LANGUAGE = 1;
+ private static int LIST_INDEX_AUDIO_CONTENT_RAW_METADATA = 2;
+
+ /* Index for BluetoothLeBroadcastChannel */
+ private static int MATCH_INDEX_CHANNEL_INDEX = 1;
+ private static int MATCH_INDEX_CHANNEL_CODEC_CONFIG = 2;
private BluetoothLeBroadcastSubgroup mSubgroup;
private List<BluetoothLeBroadcastSubgroup> mSubgroupList;
@@ -55,17 +94,20 @@
private byte[] mBroadcastCode;
// BluetoothLeBroadcastSubgroup
- private long mCodecId;
+ private int mCodecId;
private BluetoothLeAudioContentMetadata mContentMetadata;
private BluetoothLeAudioCodecConfigMetadata mConfigMetadata;
- private BluetoothLeBroadcastChannel mChannel;
+ private Boolean mNoChannelPreference;
+ private List<BluetoothLeBroadcastChannel> mChannel;
// BluetoothLeAudioCodecConfigMetadata
private long mAudioLocation;
+ private byte[] mCodecConfigMetadata;
// BluetoothLeAudioContentMetadata
private String mLanguage;
private String mProgramInfo;
+ private byte[] mAudioContentMetadata;
// BluetoothLeBroadcastChannel
private boolean mIsSelected;
@@ -135,6 +177,7 @@
for (BluetoothLeBroadcastSubgroup subgroup: subgroupList) {
String audioCodec = convertAudioCodecConfigToString(subgroup.getCodecSpecificConfig());
String audioContent = convertAudioContentToString(subgroup.getContentMetadata());
+ boolean hasChannelPreference = subgroup.hasChannelPreference();
String channels = convertChannelToString(subgroup.getChannels());
subgroupString = new StringBuilder()
.append(BluetoothBroadcastUtils.PREFIX_BTSG_CODEC_ID)
@@ -146,6 +189,9 @@
.append(BluetoothBroadcastUtils.PREFIX_BTSG_AUDIO_CONTENT)
.append(METADATA_START).append(audioContent).append(METADATA_END)
.append(BluetoothBroadcastUtils.DELIMITER_QR_CODE)
+ .append(BluetoothBroadcastUtils.PREFIX_BTSG_CHANNEL_PREF)
+ .append(METADATA_START).append(hasChannelPreference).append(METADATA_END)
+ .append(BluetoothBroadcastUtils.DELIMITER_QR_CODE)
.append(BluetoothBroadcastUtils.PREFIX_BTSG_BROADCAST_CHANNEL)
.append(METADATA_START).append(channels).append(METADATA_END)
.append(BluetoothBroadcastUtils.DELIMITER_QR_CODE)
@@ -211,26 +257,35 @@
if (DEBUG) {
Log.d(TAG, "Convert " + qrCodeString + "to BluetoothLeBroadcastMetadata");
}
- Pattern pattern = Pattern.compile(PATTERN_REGEX);
+
+ Pattern pattern = Pattern.compile(PATTERN_BT_BROADCAST_METADATA);
Matcher match = pattern.matcher(qrCodeString);
if (match.find()) {
- ArrayList<String> resultList = new ArrayList<>();
- resultList.add(match.group(1));
- mSourceAddressType = Integer.parseInt(resultList.get(0));
+ mSourceAddressType = Integer.parseInt(match.group(MATCH_INDEX_ADDRESS_TYPE));
mSourceDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(
- resultList.get(1));
- mSourceAdvertisingSid = Integer.parseInt(resultList.get(2));
- mBroadcastId = Integer.parseInt(resultList.get(3));
- mPaSyncInterval = Integer.parseInt(resultList.get(4));
- mIsEncrypted = Boolean.valueOf(resultList.get(5));
- mBroadcastCode = resultList.get(6).getBytes();
- mPresentationDelayMicros = Integer.parseInt(resultList.get(7));
- mSubgroup = convertToSubgroup(resultList.get(8));
+ match.group(MATCH_INDEX_DEVICE));
+ mSourceAdvertisingSid = Integer.parseInt(match.group(MATCH_INDEX_ADVERTISING_SID));
+ mBroadcastId = Integer.parseInt(match.group(MATCH_INDEX_BROADCAST_ID));
+ mPaSyncInterval = Integer.parseInt(match.group(MATCH_INDEX_SYNC_INTERVAL));
+ mIsEncrypted = Boolean.valueOf(match.group(MATCH_INDEX_IS_ENCRYPTED));
+ mBroadcastCode = match.group(MATCH_INDEX_BROADCAST_CODE).getBytes();
+ mPresentationDelayMicros =
+ Integer.parseInt(match.group(MATCH_INDEX_PRESENTATION_DELAY));
if (DEBUG) {
- Log.d(TAG, "Converted qrCodeString result: " + match.group());
+ Log.d(TAG, "Converted qrCodeString result: "
+ + " ,Type = " + mSourceAddressType
+ + " ,Device = " + mSourceDevice
+ + " ,AdSid = " + mSourceAdvertisingSid
+ + " ,BroadcastId = " + mBroadcastId
+ + " ,paSync = " + mPaSyncInterval
+ + " ,encrypted = " + mIsEncrypted
+ + " ,BroadcastCode = " + Arrays.toString(mBroadcastCode)
+ + " ,delay = " + mPresentationDelayMicros);
}
+ mSubgroup = convertToSubgroup(match.group(MATCH_INDEX_SUBGROUPS));
+
return new BluetoothLeBroadcastMetadata.Builder()
.setSourceDevice(mSourceDevice, mSourceAddressType)
.setSourceAdvertisingSid(mSourceAdvertisingSid)
@@ -254,26 +309,26 @@
if (DEBUG) {
Log.d(TAG, "Convert " + subgroupString + "to BluetoothLeBroadcastSubgroup");
}
- Pattern pattern = Pattern.compile(PATTERN_REGEX);
+ Pattern pattern = Pattern.compile(PATTERN_BT_SUBGROUP);
Matcher match = pattern.matcher(subgroupString);
if (match.find()) {
- ArrayList<String> resultList = new ArrayList<>();
- resultList.add(match.group(1));
- mCodecId = Long.getLong(resultList.get(0));
- mConfigMetadata = convertToConfigMetadata(resultList.get(1));
- mContentMetadata = convertToContentMetadata(resultList.get(2));
- mChannel = convertToChannel(resultList.get(3), mConfigMetadata);
+ mCodecId = Integer.parseInt(match.group(MATCH_INDEX_CODEC_ID));
+ mConfigMetadata = convertToConfigMetadata(match.group(MATCH_INDEX_CODEC_CONFIG));
+ mContentMetadata = convertToContentMetadata(match.group(MATCH_INDEX_AUDIO_CONTENT));
+ mNoChannelPreference = Boolean.valueOf(match.group(MATCH_INDEX_CHANNEL_PREF));
+ mChannel =
+ convertToChannel(match.group(MATCH_INDEX_BROADCAST_CHANNEL), mConfigMetadata);
- if (DEBUG) {
- Log.d(TAG, "Converted subgroupString result: " + match.group());
+ BluetoothLeBroadcastSubgroup.Builder subgroupBuilder =
+ new BluetoothLeBroadcastSubgroup.Builder();
+ subgroupBuilder.setCodecId(mCodecId);
+ subgroupBuilder.setCodecSpecificConfig(mConfigMetadata);
+ subgroupBuilder.setContentMetadata(mContentMetadata);
+
+ for (BluetoothLeBroadcastChannel channel : mChannel) {
+ subgroupBuilder.addChannel(channel);
}
-
- return new BluetoothLeBroadcastSubgroup.Builder()
- .setCodecId(mCodecId)
- .setCodecSpecificConfig(mConfigMetadata)
- .setContentMetadata(mContentMetadata)
- .addChannel(mChannel)
- .build();
+ return subgroupBuilder.build();
} else {
if (DEBUG) {
Log.d(TAG,
@@ -291,15 +346,17 @@
}
Pattern pattern = Pattern.compile(PATTERN_REGEX);
Matcher match = pattern.matcher(configMetadataString);
- if (match.find()) {
- ArrayList<String> resultList = new ArrayList<>();
+ ArrayList<String> resultList = new ArrayList<>();
+ while (match.find()) {
resultList.add(match.group(1));
- mAudioLocation = Long.getLong(resultList.get(0));
-
- if (DEBUG) {
- Log.d(TAG, "Converted configMetadataString result: " + match.group());
- }
-
+ Log.d(TAG, "Codec Config match : " + match.group(1));
+ }
+ if (DEBUG) {
+ Log.d(TAG, "Converted configMetadataString result: " + resultList.size());
+ }
+ if (resultList.size() > 0) {
+ mAudioLocation = Long.parseLong(resultList.get(LIST_INDEX_AUDIO_LOCATION));
+ mCodecConfigMetadata = resultList.get(LIST_INDEX_CODEC_CONFIG_RAW_METADATA).getBytes();
return new BluetoothLeAudioCodecConfigMetadata.Builder()
.setAudioLocation(mAudioLocation)
.build();
@@ -319,14 +376,25 @@
}
Pattern pattern = Pattern.compile(PATTERN_REGEX);
Matcher match = pattern.matcher(contentMetadataString);
- if (match.find()) {
- ArrayList<String> resultList = new ArrayList<>();
+ ArrayList<String> resultList = new ArrayList<>();
+ while (match.find()) {
+ Log.d(TAG, "Audio Content match : " + match.group(1));
resultList.add(match.group(1));
- mProgramInfo = resultList.get(0);
- mLanguage = resultList.get(1);
+ }
+ if (DEBUG) {
+ Log.d(TAG, "Converted contentMetadataString result: " + resultList.size());
+ }
+ if (resultList.size() > 0) {
+ mProgramInfo = resultList.get(LIST_INDEX_PROGRAM_INFO);
+ mLanguage = resultList.get(LIST_INDEX_LANGUAGE);
+ mAudioContentMetadata =
+ resultList.get(LIST_INDEX_AUDIO_CONTENT_RAW_METADATA).getBytes();
- if (DEBUG) {
- Log.d(TAG, "Converted contentMetadataString result: " + match.group());
+ /* TODO(b/265253566) : Need to set the default value for language when the user starts
+ * the broadcast.
+ */
+ if (mLanguage.equals("null")) {
+ mLanguage = "eng";
}
return new BluetoothLeAudioContentMetadata.Builder()
@@ -342,28 +410,34 @@
}
}
- private BluetoothLeBroadcastChannel convertToChannel(String channelString,
+ private List<BluetoothLeBroadcastChannel> convertToChannel(String channelString,
BluetoothLeAudioCodecConfigMetadata configMetadata) {
if (DEBUG) {
Log.d(TAG, "Convert " + channelString + "to BluetoothLeBroadcastChannel");
}
- Pattern pattern = Pattern.compile(PATTERN_REGEX);
+ Pattern pattern = Pattern.compile(PATTERN_BT_CHANNEL);
Matcher match = pattern.matcher(channelString);
- if (match.find()) {
- ArrayList<String> resultList = new ArrayList<>();
- resultList.add(match.group(1));
- mIsSelected = Boolean.valueOf(resultList.get(0));
- mChannelIndex = Integer.parseInt(resultList.get(1));
+ Map<Integer, BluetoothLeAudioCodecConfigMetadata> channel =
+ new HashMap<Integer, BluetoothLeAudioCodecConfigMetadata>();
+ while (match.find()) {
+ channel.put(Integer.parseInt(match.group(MATCH_INDEX_CHANNEL_INDEX)),
+ convertToConfigMetadata(match.group(MATCH_INDEX_CHANNEL_CODEC_CONFIG)));
+ }
- if (DEBUG) {
- Log.d(TAG, "Converted channelString result: " + match.group());
+ if (channel.size() > 0) {
+ mIsSelected = false;
+ ArrayList<BluetoothLeBroadcastChannel> broadcastChannelList = new ArrayList<>();
+ for (Map.Entry<Integer, BluetoothLeAudioCodecConfigMetadata> entry :
+ channel.entrySet()) {
+
+ broadcastChannelList.add(
+ new BluetoothLeBroadcastChannel.Builder()
+ .setSelected(mIsSelected)
+ .setChannelIndex(entry.getKey())
+ .setCodecMetadata(entry.getValue())
+ .build());
}
-
- return new BluetoothLeBroadcastChannel.Builder()
- .setSelected(mIsSelected)
- .setChannelIndex(mChannelIndex)
- .setCodecMetadata(configMetadata)
- .build();
+ return broadcastChannelList;
} else {
if (DEBUG) {
Log.d(TAG,
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/IllustrationPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/IllustrationPreferenceTest.java
index 29549d9..103512d 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/IllustrationPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/IllustrationPreferenceTest.java
@@ -61,6 +61,8 @@
private PreferenceViewHolder mViewHolder;
private FrameLayout mMiddleGroundLayout;
private final Context mContext = ApplicationProvider.getApplicationContext();
+ private IllustrationPreference.OnBindListener mOnBindListener;
+ private LottieAnimationView mOnBindListenerAnimationView;
@Before
public void setUp() {
@@ -82,6 +84,12 @@
final AttributeSet attributeSet = Robolectric.buildAttributeSet().build();
mPreference = new IllustrationPreference(mContext, attributeSet);
+ mOnBindListener = new IllustrationPreference.OnBindListener() {
+ @Override
+ public void onBind(LottieAnimationView animationView) {
+ mOnBindListenerAnimationView = animationView;
+ }
+ };
}
@Test
@@ -186,4 +194,25 @@
assertThat(mBackgroundView.getMaxHeight()).isEqualTo(restrictedHeight);
assertThat(mAnimationView.getMaxHeight()).isEqualTo(restrictedHeight);
}
+
+ @Test
+ public void setOnBindListener_isNotified() {
+ mOnBindListenerAnimationView = null;
+ mPreference.setOnBindListener(mOnBindListener);
+
+ mPreference.onBindViewHolder(mViewHolder);
+
+ assertThat(mOnBindListenerAnimationView).isNotNull();
+ assertThat(mOnBindListenerAnimationView).isEqualTo(mAnimationView);
+ }
+
+ @Test
+ public void setOnBindListener_notNotified() {
+ mOnBindListenerAnimationView = null;
+ mPreference.setOnBindListener(null);
+
+ mPreference.onBindViewHolder(mViewHolder);
+
+ assertThat(mOnBindListenerAnimationView).isNull();
+ }
}
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index 90874bb..06c3476 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -123,7 +123,7 @@
Settings.Secure.FINGERPRINT_SIDE_FPS_BP_POWER_WINDOW,
Settings.Secure.FINGERPRINT_SIDE_FPS_ENROLL_TAP_WINDOW,
Settings.Secure.FINGERPRINT_SIDE_FPS_AUTH_DOWNTIME,
- Settings.Secure.SFPS_REQUIRE_SCREEN_ON_TO_AUTH_ENABLED,
+ Settings.Secure.SFPS_PERFORMANT_AUTH_ENABLED,
Settings.Secure.ACTIVE_UNLOCK_ON_WAKE,
Settings.Secure.ACTIVE_UNLOCK_ON_UNLOCK_INTENT,
Settings.Secure.ACTIVE_UNLOCK_ON_BIOMETRIC_FAIL,
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index 62f4c41..d72d4d5 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -178,7 +178,7 @@
VALIDATORS.put(Secure.FINGERPRINT_SIDE_FPS_ENROLL_TAP_WINDOW,
NON_NEGATIVE_INTEGER_VALIDATOR);
VALIDATORS.put(Secure.FINGERPRINT_SIDE_FPS_AUTH_DOWNTIME, NON_NEGATIVE_INTEGER_VALIDATOR);
- VALIDATORS.put(Secure.SFPS_REQUIRE_SCREEN_ON_TO_AUTH_ENABLED, BOOLEAN_VALIDATOR);
+ VALIDATORS.put(Secure.SFPS_PERFORMANT_AUTH_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.SHOW_MEDIA_WHEN_BYPASSING, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.FACE_UNLOCK_APP_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION, BOOLEAN_VALIDATOR);
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index d716b32..c641a85 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -620,6 +620,8 @@
<uses-permission android:name="android.permission.MANAGE_HOTWORD_DETECTION" />
<uses-permission android:name="android.permission.BIND_HOTWORD_DETECTION_SERVICE" />
+ <uses-permission android:name="android.permission.BIND_VISUAL_QUERY_DETECTION_SERVICE" />
+
<!-- Permission required for CTS test - KeyguardLockedStateApiTest -->
<uses-permission android:name="android.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE" />
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index 854d96e..697e181 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -272,6 +272,7 @@
"LowLightDreamLib",
"motion_tool_lib",
"androidx.core_core-animation-testing-nodeps",
+ "androidx.compose.ui_ui",
],
}
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 4be1d30..115cf792 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -296,7 +296,7 @@
<queries>
<intent>
- <action android:name="android.intent.action.NOTES" />
+ <action android:name="android.intent.action.CREATE_NOTE" />
</intent>
</queries>
@@ -343,6 +343,7 @@
<protected-broadcast android:name="com.android.settingslib.action.REGISTER_SLICE_RECEIVER" />
<protected-broadcast android:name="com.android.settingslib.action.UNREGISTER_SLICE_RECEIVER" />
<protected-broadcast android:name="com.android.settings.flashlight.action.FLASHLIGHT_CHANGED" />
+ <protected-broadcast android:name="com.android.systemui.STARTED" />
<application
android:name=".SystemUIApplication"
@@ -415,7 +416,6 @@
<service android:name=".screenshot.ScreenshotCrossProfileService"
android:permission="com.android.systemui.permission.SELF"
- android:process=":screenshot_cross_profile"
android:exported="false" />
<service android:name=".screenrecord.RecordingService"
@@ -1005,7 +1005,6 @@
<action android:name="com.android.systemui.action.LAUNCH_MEDIA_OUTPUT_DIALOG" />
<action android:name="com.android.systemui.action.LAUNCH_MEDIA_OUTPUT_BROADCAST_DIALOG" />
<action android:name="com.android.systemui.action.DISMISS_MEDIA_OUTPUT_DIALOG" />
- <action android:name="android.intent.action.SHOW_OUTPUT_SWITCHER" />
</intent-filter>
</receiver>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/Android.bp b/packages/SystemUI/accessibility/accessibilitymenu/Android.bp
index a494f5e..0b1a3e2 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/Android.bp
+++ b/packages/SystemUI/accessibility/accessibilitymenu/Android.bp
@@ -20,6 +20,17 @@
android_app {
name: "AccessibilityMenu",
+
+ static_libs: [
+ "androidx.coordinatorlayout_coordinatorlayout",
+ "androidx.core_core",
+ "androidx.viewpager_viewpager",
+ ],
+
+ uses_libs: [
+ "org.apache.http.legacy",
+ ],
+
srcs: [
"src/**/*.java",
],
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/color/footer_icon_tint_color.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/color/footer_icon_tint_color.xml
new file mode 100644
index 0000000..c89e4c3
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/color/footer_icon_tint_color.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_enabled="false"
+ android:color="@color/footer_icon_disabled_color" /> <!-- disabled -->
+ <item android:color="@color/footer_icon_enabled_color" /> <!-- default -->
+</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/a11ymenu_intro.png b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/a11ymenu_intro.png
new file mode 100644
index 0000000..6149ee4
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/a11ymenu_intro.png
Binary files differ
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/footer_button_background_left.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/footer_button_background_left.xml
new file mode 100644
index 0000000..5ff245d
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/footer_button_background_left.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item>
+ <ripple
+ android:color="@color/ripple_material_color">
+ <item android:id="@android:id/mask">
+ <color android:color="@color/overlay_bg_color"/>
+ </item>
+ </ripple>
+ </item>
+
+</layer-list>
\ No newline at end of file
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/footer_button_background_right.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/footer_button_background_right.xml
new file mode 100644
index 0000000..5ff245d
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/footer_button_background_right.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item>
+ <ripple
+ android:color="@color/ripple_material_color">
+ <item android:id="@android:id/mask">
+ <color android:color="@color/overlay_bg_color"/>
+ </item>
+ </ripple>
+ </item>
+
+</layer-list>
\ No newline at end of file
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_a11y_menu_round.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_a11y_menu_round.xml
new file mode 100644
index 0000000..a2eaf95
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_a11y_menu_round.xml
@@ -0,0 +1,20 @@
+<!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<vector android:height="108dp" android:viewportHeight="24"
+ android:viewportWidth="24" android:width="108dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="#ffffff" android:fillType="evenOdd" android:pathData="M7.875,10.625C7.1188,10.625 6.5,11.2437 6.5,12C6.5,12.7562 7.1188,13.375 7.875,13.375C8.6313,13.375 9.25,12.7562 9.25,12C9.25,11.2437 8.6313,10.625 7.875,10.625ZM16.125,10.625C15.3687,10.625 14.75,11.2437 14.75,12C14.75,12.7562 15.3687,13.375 16.125,13.375C16.8813,13.375 17.5,12.7562 17.5,12C17.5,11.2437 16.8813,10.625 16.125,10.625ZM10.625,12C10.625,11.2437 11.2438,10.625 12,10.625C12.7563,10.625 13.375,11.2437 13.375,12C13.375,12.7562 12.7563,13.375 12,13.375C11.2438,13.375 10.625,12.7562 10.625,12Z"/>
+</vector>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_add_32dp.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_add_32dp.xml
new file mode 100644
index 0000000..7e1262c
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_add_32dp.xml
@@ -0,0 +1,5 @@
+<vector android:height="32dp" android:tint="#FFFFFF"
+ android:viewportHeight="24.0" android:viewportWidth="24.0"
+ android:width="32dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="#FF000000" android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
+</vector>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_arrow_back_24dp.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_arrow_back_24dp.xml
new file mode 100644
index 0000000..f6af270
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_arrow_back_24dp.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="@dimen/footer_arrow_length"
+ android:height="@dimen/footer_arrow_length"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="@color/footer_icon_color"
+ android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/>
+</vector>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_arrow_forward_24dp.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_arrow_forward_24dp.xml
new file mode 100644
index 0000000..2f7b632
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_arrow_forward_24dp.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="@dimen/footer_arrow_length"
+ android:height="@dimen/footer_arrow_length"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="@color/footer_icon_color"
+ android:pathData="M12,4l-1.41,1.41L16.17,11H4v2h12.17l-5.58,5.59L12,20l8,-8z"/>
+</vector>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_menu.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_menu.xml
new file mode 100644
index 0000000..79e0e08d
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_menu.xml
@@ -0,0 +1,33 @@
+<vector android:height="48dp" android:viewportHeight="192.0"
+ android:viewportWidth="192.0" android:width="48dp"
+ xmlns:aapt="http://schemas.android.com/aapt" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="#34a853" android:pathData="M37.14,173.74l-28.53,-90a14.53,14.53 0,0 1,5 -15.63L87.15,11a14.21,14.21 0,0 1,17.61 0.12l73.81,58.94a14.53,14.53 0,0 1,4.8 15.57l-28.48,88.18A14.32,14.32 0,0 1,141.22 184H50.84A14.33,14.33 0,0 1,37.14 173.74Z"/>
+ <path android:pathData="M137.61,94.07l-17,17 -17,-17 -17,17L70.3,94.72l-17,17L125.66,184h15.56a14.32,14.32 0,0 0,13.67 -10.19l15.25,-47.21Z">
+ <aapt:attr name="android:fillColor">
+ <gradient android:endX="27152.64"
+ android:endY="32745.600000000002"
+ android:startX="20910.72"
+ android:startY="21934.079999999998" android:type="linear">
+ <item android:color="#33263238" android:offset="0.0"/>
+ <item android:color="#11205432" android:offset="0.47"/>
+ <item android:color="#051E6130" android:offset="1.0"/>
+ </gradient>
+ </aapt:attr>
+ </path>
+ <path android:fillAlpha="0.2" android:fillColor="#263238" android:pathData="M50.14,100.11a12,12 0,1 1,11.39 15.77,11.72 11.72,0 0,1 -5,-1.1l-3.41,-3.4ZM129.4,91.88a12,12 0,1 1,-12 12A12,12 0,0 1,129.4 91.88ZM95.4,91.88a12,12 0,1 1,-12 12A12,12 0,0 1,95.42 91.88Z"/>
+ <path android:fillColor="#fff"
+ android:pathData="M61.53,90.88a12,12 0,1 1,-12 12A12,12 0,0 1,61.53 90.88ZM129.41,90.88a12,12 0,1 1,-12 12A12,12 0,0 1,129.41 90.88ZM95.41,90.88a12,12 0,1 1,-12 12A12,12 0,0 1,95.42 90.88Z"
+ android:strokeAlpha="0" android:strokeColor="#000"
+ android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="0.5"/>
+ <path android:fillAlpha="0.2" android:fillColor="#263238" android:pathData="M184,80.91a14.33,14.33 0,0 1,-0.63 4.7l-28.48,88.18A14.33,14.33 0,0 1,141.21 184H50.84a14.33,14.33 0,0 1,-13.7 -10.26l-28.53,-90A14.49,14.49 0,0 1,8 79.11a14.3,14.3 0,0 0,0.61 3.64l28.53,90A14.33,14.33 0,0 0,50.84 183h90.37a14.33,14.33 0,0 0,13.67 -10.19l28.48,-88.18A14.79,14.79 0,0 0,184 80.91Z"/>
+ <path android:fillAlpha="0.2" android:fillColor="#fff" android:pathData="M184,81.89A14.46,14.46 0,0 0,178.57 71L104.76,12.1A14.21,14.21 0,0 0,87.15 12L13.58,69.12A14.5,14.5 0,0 0,8 80.09a14.5,14.5 0,0 1,5.57 -12L87.15,11a14.21,14.21 0,0 1,17.61 0.12L178.57,70A14.48,14.48 0,0 1,184 81.89Z"/>
+ <path android:pathData="M37.14,173.74l-28.53,-90a14.53,14.53 0,0 1,5 -15.63L87.15,11a14.21,14.21 0,0 1,17.61 0.12l73.81,58.94a14.53,14.53 0,0 1,4.8 15.57l-28.48,88.18A14.32,14.32 0,0 1,141.22 184H50.84A14.33,14.33 0,0 1,37.14 173.74Z"/>
+ <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@color/colorAccessibilityMenuIcon" />
+ <foreground>
+ <inset
+ android:drawable="@drawable/ic_a11y_menu_round"
+ android:inset="21.88%" />
+ </foreground>
+ </adaptive-icon>
+</vector>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_assistant_32dp.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_assistant_32dp.xml
new file mode 100644
index 0000000..ebeebf8
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_assistant_32dp.xml
@@ -0,0 +1,8 @@
+<vector android:height="32dp"
+ android:viewportHeight="192.0" android:viewportWidth="192.0"
+ android:width="32dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="#34A853" android:pathData="M172,60m-12,0a12,12 0,1 1,24 0a12,12 0,1 1,-24 0"/>
+ <path android:fillColor="#EA4335" android:pathData="M136,88m-24,0a24,24 0,1 1,48 0a24,24 0,1 1,-48 0"/>
+ <path android:fillColor="#FBBC05" android:pathData="M136,148m-28,0a28,28 0,1 1,56 0a28,28 0,1 1,-56 0"/>
+ <path android:fillColor="#4285F4" android:pathData="M56,64m-48,0a48,48 0,1 1,96 0a48,48 0,1 1,-96 0"/>
+</vector>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/shadow_0deg.9.png b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/shadow_0deg.9.png
new file mode 100644
index 0000000..b0d1696
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/shadow_0deg.9.png
Binary files differ
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/shadow_270deg.9.png b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/shadow_270deg.9.png
new file mode 100644
index 0000000..b777ffe
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/shadow_270deg.9.png
Binary files differ
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/shadow_90deg.9.png b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/shadow_90deg.9.png
new file mode 100644
index 0000000..998bd90
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/shadow_90deg.9.png
Binary files differ
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/view_background.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/view_background.xml
new file mode 100644
index 0000000..c1f76f37
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/view_background.xml
@@ -0,0 +1,5 @@
+<shape
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <solid android:color="@color/overlay_bg_color" />
+</shape>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/layout/footerlayout_switch_page.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/layout/footerlayout_switch_page.xml
new file mode 100644
index 0000000..658c03b
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/layout/footerlayout_switch_page.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/footerlayout"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/grid_item_btn_view_height"
+ android:layout_alignParentBottom="true"
+ android:layout_gravity="bottom"
+ android:layoutDirection="ltr"
+ android:orientation="vertical"
+ android:visibility="gone">
+
+ <View
+ android:id="@+id/top_listDivider"
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:background="?android:attr/listDivider"/>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:orientation="horizontal">
+
+ <ImageButton
+ android:id="@+id/menu_prev_button"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:background="@drawable/footer_button_background_left"
+ android:contentDescription="@string/previous_button_content_description"
+ android:scaleType="centerInside"
+ android:src="@drawable/ic_arrow_back_24dp"
+ android:tint="@color/footer_icon_tint_color"/>
+
+ <View
+ android:layout_width="1dp"
+ android:layout_height="match_parent"
+ android:background="?android:attr/listDivider"/>
+
+ <ImageButton
+ android:id="@+id/menu_next_button"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:background="@drawable/footer_button_background_right"
+ android:contentDescription="@string/next_button_content_description"
+ android:scaleType="centerInside"
+ android:src="@drawable/ic_arrow_forward_24dp"
+ android:tint="@color/footer_icon_tint_color"/>
+
+ </LinearLayout>
+
+ <View
+ android:id="@+id/bottom_listDivider"
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:background="?android:attr/listDivider"/>
+
+</LinearLayout>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/layout/grid_item.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/layout/grid_item.xml
new file mode 100644
index 0000000..39e5a8c
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/layout/grid_item.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingTop="@dimen/grid_item_padding"
+ android:paddingBottom="@dimen/grid_item_padding"
+ android:gravity="center">
+
+ <ImageButton
+ android:id="@+id/shortcutIconBtn"
+ android:layout_width="@dimen/image_button_width"
+ android:layout_height="@dimen/image_button_height"
+ android:layout_alignParentTop="true"
+ android:layout_centerHorizontal="true"
+ android:scaleType="fitCenter"></ImageButton>
+
+<TextView
+ android:id="@+id/shortcutLabel"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/grid_item_text_view_margin_top"
+ android:layout_below="@+id/shortcutIconBtn"
+ android:layout_centerHorizontal="true"
+ android:ellipsize="end"
+ android:gravity="center_horizontal"
+ android:importantForAccessibility="no"
+ android:lines="2"
+ android:textSize="@dimen/label_text_size"
+ android:textAlignment="center"
+ android:textAppearance="@android:style/TextAppearance.DeviceDefault.Widget.Button"/>
+
+</RelativeLayout>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/layout/grid_view.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/layout/grid_view.xml
new file mode 100644
index 0000000..c198443
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/layout/grid_view.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<GridView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/gridview"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:horizontalSpacing="@dimen/a11ymenu_grid_layout_margin"
+ android:listSelector="@android:color/transparent"
+ android:numColumns="3"
+ android:overScrollMode="never"
+ android:stretchMode="columnWidth">
+</GridView>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/layout/paged_menu.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/layout/paged_menu.xml
new file mode 100644
index 0000000..28a633e
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/layout/paged_menu.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="@dimen/row_width"
+ android:layout_height="match_parent"
+ android:id="@+id/coordinatorLayout"
+ android:background="@drawable/view_background"
+ >
+ <LinearLayout
+ android:layout_width="@dimen/row_width"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <androidx.viewpager.widget.ViewPager
+ android:id="@+id/view_pager"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="@dimen/table_margin_top"
+ android:paddingBottom="@dimen/a11ymenu_layout_margin"
+ android:paddingLeft="@dimen/a11ymenu_layout_margin"
+ android:paddingRight="@dimen/a11ymenu_layout_margin"
+ android:layout_gravity="center"
+ android:gravity="center"
+ />
+
+ <include layout="@layout/footerlayout_switch_page"/>
+ </LinearLayout>
+</androidx.coordinatorlayout.widget.CoordinatorLayout>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-land/dimens.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-land/dimens.xml
new file mode 100644
index 0000000..69f0934
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-land/dimens.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <dimen name="table_margin_top">0dp</dimen>
+ <dimen name="row_width">388dp</dimen>
+ <dimen name="image_button_height">45dp</dimen>
+ <dimen name="image_button_width">45dp</dimen>
+ <dimen name="image_button_marginBottom">1dp</dimen>
+
+ <!-- dimens for gridview layout. -->
+ <dimen name="grid_item_padding">4dp</dimen>
+
+</resources>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-night/colors.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-night/colors.xml
new file mode 100644
index 0000000..33c0cca
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-night/colors.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<resources>
+ <color name="power_color">#dadce0</color>
+ <color name="quick_settings_color">#78d9ec</color>
+ <color name="a11y_settings_color">#d9affe</color>
+ <color name="recent_apps_color">#f0a5dd</color>
+ <color name="lockscreen_color">#85e4a0</color>
+ <color name="volume_color">#7ae3d4</color>
+ <color name="notifications_color">#f496ac</color>
+ <color name="screenshot_color">#adcbff</color>
+ <color name="assistant_color">#F1F3F4</color>
+ <color name="brightness_color">#fdd663</color>
+
+ <color name="ripple_material_color">#10FFFFFF</color>
+
+ <color name="overlay_bg_color">#313235</color>
+ <color name="footer_icon_color">#E8EAED</color>
+ <color name="footer_icon_enabled_color">#E8EAED</color>
+ <color name="footer_icon_disabled_color">#5F6368</color>
+ <color name="colorControlNormal">#202124</color>
+
+</resources>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-night/styles.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-night/styles.xml
new file mode 100644
index 0000000..81b3152
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-night/styles.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources>
+ <!--Adds the theme to support SnackBar component and user configurable theme. -->
+ <style name="ServiceTheme" parent="android:Theme.DeviceDefault.DayNight">
+ <item name="android:colorControlNormal">@color/colorControlNormal</item>
+ </style>
+
+</resources>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values/bool.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values/bool.xml
new file mode 100644
index 0000000..2f9d6b5
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values/bool.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <bool name="isAtLeastP">true</bool>
+
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values/colors.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values/colors.xml
new file mode 100644
index 0000000..36d1fc1
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values/colors.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<resources>
+ <color name="power_color">#757575</color>
+ <color name="quick_settings_color">#2196F3</color>
+ <color name="a11y_settings_color">#5806C9</color>
+ <color name="recent_apps_color">#AD2EC6</color>
+ <color name="lockscreen_color">#0F9D58</color>
+ <color name="volume_color">#01A2A0</color>
+ <color name="notifications_color">#F15B8D</color>
+ <color name="screenshot_color">#26459C</color>
+ <color name="assistant_color">#F1F3F4</color>
+ <color name="brightness_color">#E59810</color>
+ <color name="colorAccent">#1a73e8</color>
+
+ <color name="ripple_material_color">#1f000000</color>
+
+ <color name="overlay_bg_color">@android:color/white</color>
+ <color name="footer_icon_color">@android:color/black</color>
+ <color name="footer_icon_enabled_color">@android:color/black</color>
+ <color name="footer_icon_disabled_color">#ddd</color>
+ <color name="colorControlNormal">@android:color/white</color>
+
+ <color name="colorAccessibilityMenuIcon">#3AA757</color>
+</resources>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values/dimens.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values/dimens.xml
new file mode 100644
index 0000000..7ed1897
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values/dimens.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- the curve radius for the background of the complete layout -->
+ <dimen name="table_margin_top">22dp</dimen>
+ <dimen name="row_width">@dimen/custom_match_parent</dimen>
+ <dimen name="image_button_height">60dp</dimen>
+ <dimen name="image_button_width">60dp</dimen>
+ <dimen name="image_button_marginBottom">2dp</dimen>
+ <dimen name="a11ymenu_layout_margin">4dp</dimen>
+ <dimen name="custom_match_parent">-1px</dimen>
+
+ <!-- dimens for gridview layout. -->
+ <dimen name="grid_item_text_view_margin_top">2dp</dimen>
+ <dimen name="grid_item_padding">10dp</dimen>
+ <dimen name="grid_item_btn_view_height">48dp</dimen>
+ <dimen name="a11ymenu_grid_layout_margin">8dp</dimen>
+
+ <!-- dimens for a11y menu footer layout. -->
+ <dimen name="footer_arrow_length">24dp</dimen>
+
+ <!-- text size for shortcut label when large button settings in on. -->
+ <dimen name="large_label_text_size">18sp</dimen>
+ <dimen name="label_text_size">14sp</dimen>
+
+</resources>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values/donottranslate.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values/donottranslate.xml
new file mode 100644
index 0000000..0c25ec4
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values/donottranslate.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- user customized shortcuts preference -->
+ <string name="pref_user_shortcuts">accessibility_menu_user_shortcuts</string>
+ <!-- key for user customized shortcuts -->
+ <string name="pref_user_shortcuts_key">pref_user_shortcuts_key</string>
+ <!-- value for empty shortcut -->
+ <string name="pref_user_shortcuts_value_empty">[]</string>
+ <!-- empty string for shortcut label -->
+ <string name="empty_content"></string>
+
+ <string name="pref_large_buttons">pref_large_buttons</string>
+
+ <!-- key for Help&feedback settings [CHAR_LIMIT=NONE] -->
+ <string name="pref_help">pref_help</string>
+
+</resources>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values/strings.xml
new file mode 100644
index 0000000..30fd017
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values/strings.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- String defining the service name -->
+ <string name="accessibility_menu_service_name">Accessibility Menu</string>
+ <!-- Accessibility Menu detail intro. [CHAR_LIMIT=NONE] -->
+ <string name="accessibility_menu_intro">
+ The Accessibility Menu provides a large on-screen menu to control your device. You can lock your device, control volume and brightness, take screenshots, and more.
+ </string>
+ <!-- String defining the label for the assistant button -->
+ <string name="assistant_label">Assistant</string>
+ <!-- String defining utterance for the assistant button for screen readers -->
+ <string name="assistant_utterance">Google Assistant</string>
+ <!-- String defining the label for the accessibility settings button -->
+ <string name="a11y_settings_label">Accessibility Settings</string>
+ <!-- String defining the label for the volume button -->
+ <string name="volume_label">Volume</string>
+ <!-- String defining utterance for the volume button for screen readers -->
+ <string name="volume_utterance">Volume controls</string>
+ <!-- String defining the label for the power button -->
+ <string name="power_label">Power</string>
+ <!-- String defining utterance for the power button for screen readers -->
+ <string name="power_utterance">Power options</string>
+ <!-- String defining the label for the recent apps button -->
+ <string name="recent_apps_label">Recent apps</string>
+ <!-- String defining the label for the lockscreen button -->
+ <string name="lockscreen_label">Lock screen</string>
+ <!-- String defining the label for the quick settings button -->
+ <string name="quick_settings_label">Quick Settings</string>
+ <!-- String defining the label for the notifications button -->
+ <string name="notifications_label">Notifications</string>
+ <!-- String defining the label for the screenshot button -->
+ <string name="screenshot_label">Screenshot</string>
+ <!-- String defining the utterance for the screenshot button for screen readers -->
+ <string name="screenshot_utterance">Take screenshot</string>
+ <!-- String defining the label for the volume up/down button -->
+ <string name="volume_up_label">Volume up</string>
+ <string name="volume_down_label">Volume down</string>
+ <!-- String defining the label for the brightness up/down button -->
+ <string name="brightness_up_label">Brightness up</string>
+ <string name="brightness_down_label">Brightness down</string>
+ <!-- String defining the content description for the footer previous/next button -->
+ <string name="previous_button_content_description">Go to previous screen</string>
+ <string name="next_button_content_description">Go to next screen</string>
+
+ <string name="accessibility_menu_description">
+ The Accessibility Menu provides a large on-screen menu to control your device. You can lock your device, control volume and brightness, take screenshots, and more.
+ </string>
+ <!-- Short summary of app that appears as subtext on the service preference in Settings -->
+ <string name="accessibility_menu_summary">Control device via large menu</string>
+
+ <!-- TODO(b/113371047): string need to be reviewed -->
+ <!-- String defining the settings name -->
+ <string name="accessibility_menu_settings_name">Accessibility Menu Settings</string>
+
+ <!-- String defining the title of Large button setting -->
+ <string name="accessibility_menu_large_buttons_title">Large buttons</string>
+ <!-- String defining the summary of Large button setting -->
+ <string name="accessibility_menu_large_buttons_summary">Increase size of Accessibility Menu Buttons</string>
+ <!-- String defining the title of the preference to show help and feedback menu [CHAR LIMIT=40] -->
+ <string name="pref_help_and_feedback_title">Help & feedback</string>
+ <!-- String defining the title of the preference to show help menu [CHAR LIMIT=40] -->
+ <string name="pref_help_title">Help</string>
+
+ <!-- The percentage of the brightness, and double "%" is required to represent the symbol "%" -->
+ <string name="brightness_percentage_label">Brightness <xliff:g id="percentage">%1$s</xliff:g> %%</string>
+ <!-- The percentage of the music volume, and double "%" is required to represent the symbol "%" -->
+ <string name="music_volume_percentage_label">Music volume <xliff:g id="percentage">%1$s</xliff:g> %%</string>
+
+ <!-- The label of a settings item that displays legal information about the licenses used in this app. [CHAR LIMIT=NONE] -->
+ <string name="pref_item_licenses">Open Source Licenses</string>
+
+</resources>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values/styles.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values/styles.xml
new file mode 100644
index 0000000..a2cf267
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values/styles.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources>
+ <!--The theme is for preference CollapsingToolbarBaseActivity settings-->
+ <style name="AccessibilityMenuSettings" parent="android:Theme.DeviceDefault.Light" />
+
+ <!--Adds the theme to support SnackBar component and user configurable theme. -->
+ <style name="ServiceTheme" parent="android:Theme.DeviceDefault.Light">
+ <item name="android:colorControlNormal">@color/colorControlNormal</item>
+ </style>
+
+ <!--The basic theme for service and test case only-->
+ <style name="A11yMenuBaseTheme" parent="android:Theme.DeviceDefault.Light">
+ <item name="android:windowActionBar">false</item>
+ </style>
+</resources>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/xml/accessibilitymenu_service.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/xml/accessibilitymenu_service.xml
index 96882d33..3dbbb1a 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/xml/accessibilitymenu_service.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/xml/accessibilitymenu_service.xml
@@ -13,4 +13,12 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"/>
\ No newline at end of file
+<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
+ android:accessibilityFeedbackType="feedbackGeneric"
+ android:accessibilityFlags="flagRequestAccessibilityButton|flagRequestFilterKeyEvents"
+ android:canRequestFilterKeyEvents="true"
+ android:summary="@string/accessibility_menu_summary"
+ android:intro="@string/accessibility_menu_intro"
+ android:animatedImageDrawable="@drawable/a11ymenu_intro"
+ android:isAccessibilityTool="true"
+/>
\ No newline at end of file
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/AccessibilityMenuService.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/AccessibilityMenuService.java
index 8b75900..5c4fdcc 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/AccessibilityMenuService.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/AccessibilityMenuService.java
@@ -17,16 +17,39 @@
package com.android.systemui.accessibility.accessibilitymenu;
import android.accessibilityservice.AccessibilityService;
+import android.view.MotionEvent;
+import android.view.View;
import android.view.accessibility.AccessibilityEvent;
+import com.android.systemui.accessibility.accessibilitymenu.view.A11yMenuOverlayLayout;
+
/** @hide */
-public class AccessibilityMenuService extends AccessibilityService {
+public class AccessibilityMenuService extends AccessibilityService implements View.OnTouchListener {
+ private static final String TAG = "A11yMenuService";
+
+ private A11yMenuOverlayLayout mA11yMenuLayout;
@Override
- public void onAccessibilityEvent(AccessibilityEvent event) {
+ public void onCreate() {
+ super.onCreate();
}
@Override
+ protected void onServiceConnected() {
+ mA11yMenuLayout = new A11yMenuOverlayLayout(this);
+ super.onServiceConnected();
+ mA11yMenuLayout.toggleVisibility();
+ }
+
+ @Override
+ public void onAccessibilityEvent(AccessibilityEvent event) {}
+
+ @Override
public void onInterrupt() {
}
+
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ return false;
+ }
}
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/model/A11yMenuShortcut.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/model/A11yMenuShortcut.java
new file mode 100644
index 0000000..fa42e61
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/model/A11yMenuShortcut.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.accessibility.accessibilitymenu.model;
+
+import com.android.systemui.accessibility.accessibilitymenu.R;
+
+/** Provides a data structure for a11y menu shortcuts. */
+public class A11yMenuShortcut {
+
+ public enum ShortcutId {
+ UNSPECIFIED_ID_VALUE,
+ ID_ASSISTANT_VALUE,
+ ID_A11YSETTING_VALUE,
+ ID_POWER_VALUE,
+ ID_VOLUME_DOWN_VALUE,
+ ID_VOLUME_UP_VALUE,
+ ID_RECENT_VALUE,
+ ID_BRIGHTNESS_DOWN_VALUE,
+ ID_BRIGHTNESS_UP_VALUE,
+ ID_LOCKSCREEN_VALUE,
+ ID_QUICKSETTING_VALUE,
+ ID_NOTIFICATION_VALUE,
+ ID_SCREENSHOT_VALUE
+ }
+
+ private static final String TAG = "A11yMenuShortcut";
+
+ /** Shortcut id used to identify. */
+ private int mShortcutId = ShortcutId.UNSPECIFIED_ID_VALUE.ordinal();
+
+ // Resource IDs of shortcut button and label.
+ public int imageSrc;
+ public int imageColor;
+ public int imgContentDescription;
+ public int labelText;
+
+ public A11yMenuShortcut(int id) {
+ setId(id);
+ }
+
+ /**
+ * Sets Id to shortcut, checks the value first and updates shortcut resources. It will set id to
+ *
+ * @param id id set to shortcut
+ */
+ public void setId(int id) {
+ mShortcutId = id;
+
+ // TODO(jonesriley) load the proper resources based on id
+ imageSrc = R.drawable.ic_logo_assistant_32dp;
+ imageColor = android.R.color.darker_gray;
+ imgContentDescription = R.string.empty_content;
+ labelText = R.string.empty_content;
+ }
+
+ public int getId() {
+ return mShortcutId;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof A11yMenuShortcut)) {
+ return false;
+ }
+
+ A11yMenuShortcut targetObject = (A11yMenuShortcut) o;
+
+ return mShortcutId == targetObject.mShortcutId;
+ }
+
+ @Override
+ public int hashCode() {
+ return mShortcutId;
+ }
+}
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/utils/ShortcutDrawableUtils.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/utils/ShortcutDrawableUtils.java
new file mode 100644
index 0000000..28ba4b5
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/utils/ShortcutDrawableUtils.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.accessibility.accessibilitymenu.utils;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+import android.graphics.drawable.AdaptiveIconDrawable;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
+import android.graphics.drawable.RippleDrawable;
+
+import com.android.systemui.accessibility.accessibilitymenu.R;
+
+/** Creates background drawable for a11y menu shortcut. */
+public class ShortcutDrawableUtils {
+
+ /**
+ * To make the circular background of shortcut icons have higher resolution. The higher value of
+ * LENGTH is, the higher resolution of the circular background are.
+ */
+ private static final int LENGTH = 480;
+
+ private static final int RADIUS = LENGTH / 2;
+ private static final int COORDINATE = LENGTH / 2;
+ private static final int RIPPLE_COLOR_ID = R.color.ripple_material_color;
+
+ private final Context mContext;
+ private final ColorStateList mRippleColorStateList;
+
+ // Placeholder of drawable to prevent NullPointerException
+ private final ColorDrawable mTransparentDrawable = new ColorDrawable(Color.TRANSPARENT);
+
+ public ShortcutDrawableUtils(Context context) {
+ this.mContext = context;
+
+ int rippleColor = context.getColor(RIPPLE_COLOR_ID);
+ mRippleColorStateList = ColorStateList.valueOf(rippleColor);
+ }
+
+ /**
+ * Creates a circular drawable in specific color for shortcut.
+ *
+ * @param colorResId color resource ID
+ * @return drawable circular drawable
+ */
+ public Drawable createCircularDrawable(int colorResId) {
+ Bitmap output = Bitmap.createBitmap(LENGTH, LENGTH, Config.ARGB_8888);
+ Canvas canvas = new Canvas(output);
+ int color = mContext.getColor(colorResId);
+ Paint paint = new Paint();
+ paint.setColor(color);
+ paint.setStrokeCap(Paint.Cap.ROUND);
+ paint.setStyle(Style.FILL);
+ canvas.drawCircle(COORDINATE, COORDINATE, RADIUS, paint);
+
+ BitmapDrawable drawable = new BitmapDrawable(mContext.getResources(), output);
+ return drawable;
+ }
+
+ /**
+ * Creates an adaptive icon drawable in specific color for shortcut.
+ *
+ * @param colorResId color resource ID
+ * @return drawable for adaptive icon
+ */
+ public Drawable createAdaptiveIconDrawable(int colorResId) {
+ Drawable circleLayer = createCircularDrawable(colorResId);
+ RippleDrawable rippleLayer = new RippleDrawable(mRippleColorStateList, null, null);
+
+ AdaptiveIconDrawable adaptiveIconDrawable =
+ new AdaptiveIconDrawable(circleLayer, mTransparentDrawable);
+
+ Drawable[] layers = {adaptiveIconDrawable, rippleLayer};
+ LayerDrawable drawable = new LayerDrawable(layers);
+ return drawable;
+ }
+}
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuAdapter.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuAdapter.java
new file mode 100644
index 0000000..e3401a9
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuAdapter.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.accessibility.accessibilitymenu.view;
+
+import android.graphics.Rect;
+import android.view.LayoutInflater;
+import android.view.TouchDelegate;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ImageButton;
+import android.widget.TextView;
+
+import com.android.systemui.accessibility.accessibilitymenu.AccessibilityMenuService;
+import com.android.systemui.accessibility.accessibilitymenu.R;
+import com.android.systemui.accessibility.accessibilitymenu.model.A11yMenuShortcut;
+import com.android.systemui.accessibility.accessibilitymenu.utils.ShortcutDrawableUtils;
+
+import java.util.List;
+
+/** GridView Adapter for a11y menu overlay. */
+public class A11yMenuAdapter extends BaseAdapter {
+
+ // The large scale of shortcut icon and label.
+ private static final float LARGE_BUTTON_SCALE = 1.5f;
+ private final int mLargeTextSize;
+
+ private final AccessibilityMenuService mService;
+ private final LayoutInflater mInflater;
+ private final List<A11yMenuShortcut> mShortcutDataList;
+ private final ShortcutDrawableUtils mShortcutDrawableUtils;
+
+ public A11yMenuAdapter(
+ AccessibilityMenuService service, List<A11yMenuShortcut> shortcutDataList) {
+ this.mService = service;
+ this.mShortcutDataList = shortcutDataList;
+ mInflater = LayoutInflater.from(service);
+
+ mShortcutDrawableUtils = new ShortcutDrawableUtils(service);
+
+ mLargeTextSize =
+ service.getResources().getDimensionPixelOffset(R.dimen.large_label_text_size);
+ }
+
+ @Override
+ public int getCount() {
+ return mShortcutDataList.size();
+ }
+
+ @Override
+ public Object getItem(int position) {
+ return mShortcutDataList.get(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return mShortcutDataList.get(position).getId();
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ convertView = mInflater.inflate(R.layout.grid_item, null);
+
+ A11yMenuShortcut shortcutItem = (A11yMenuShortcut) getItem(position);
+ // Sets shortcut icon and label resource.
+ configureShortcutView(convertView, shortcutItem);
+
+ expandIconTouchArea(convertView);
+ setActionForMenuShortcut(convertView);
+ return convertView;
+ }
+
+ /**
+ * Expand shortcut icon touch area to the border of grid item.
+ * The height is from the top of icon to the bottom of label.
+ * The width is from the left border of grid item to the right border of grid item.
+ */
+ private void expandIconTouchArea(View convertView) {
+ ImageButton shortcutIconButton = convertView.findViewById(R.id.shortcutIconBtn);
+ TextView shortcutLabel = convertView.findViewById(R.id.shortcutLabel);
+
+ shortcutIconButton.post(
+ () -> {
+ Rect iconHitRect = new Rect();
+ shortcutIconButton.getHitRect(iconHitRect);
+ Rect labelHitRect = new Rect();
+ shortcutLabel.getHitRect(labelHitRect);
+
+ final int widthAdjustment = iconHitRect.left;
+ iconHitRect.left = 0;
+ iconHitRect.right += widthAdjustment;
+ iconHitRect.top = 0;
+ iconHitRect.bottom = labelHitRect.bottom;
+ ((View) shortcutIconButton.getParent())
+ .setTouchDelegate(new TouchDelegate(iconHitRect, shortcutIconButton));
+ });
+ }
+
+ private void setActionForMenuShortcut(View convertView) {
+ ImageButton shortcutIconButton = convertView.findViewById(R.id.shortcutIconBtn);
+
+ shortcutIconButton.setOnClickListener(
+ (View v) -> {
+ // Handles shortcut click event by AccessibilityMenuService.
+ // service.handleClick(v);
+ });
+ }
+
+ private void configureShortcutView(View convertView, A11yMenuShortcut shortcutItem) {
+ ImageButton shortcutIconButton = convertView.findViewById(R.id.shortcutIconBtn);
+ TextView shortcutLabel = convertView.findViewById(R.id.shortcutLabel);
+
+ // TODO: Enlarge shortcut icon & label when large button setting is on.
+
+ if (shortcutItem.getId() == A11yMenuShortcut.ShortcutId.UNSPECIFIED_ID_VALUE.ordinal()) {
+ // Sets empty shortcut icon and label when the shortcut is ADD_ITEM.
+ shortcutIconButton.setImageResource(android.R.color.transparent);
+ shortcutIconButton.setBackground(null);
+ } else {
+ // Sets shortcut ID as tagId, to handle menu item click in AccessibilityMenuService.
+ shortcutIconButton.setTag(shortcutItem.getId());
+ shortcutIconButton.setContentDescription(
+ mService.getString(shortcutItem.imgContentDescription));
+ shortcutLabel.setText(shortcutItem.labelText);
+ shortcutIconButton.setImageResource(shortcutItem.imageSrc);
+
+ shortcutIconButton.setBackground(
+ mShortcutDrawableUtils.createAdaptiveIconDrawable(shortcutItem.imageColor));
+ }
+ }
+}
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuFooter.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuFooter.java
new file mode 100644
index 0000000..20c63df
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuFooter.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.accessibility.accessibilitymenu.view;
+
+import android.graphics.Rect;
+import android.view.TouchDelegate;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver.OnGlobalLayoutListener;
+import android.widget.ImageButton;
+
+import androidx.annotation.Nullable;
+
+import com.android.systemui.accessibility.accessibilitymenu.R;
+
+/**
+ * This class is for Accessibility menu footer layout. Handles switching between a11y menu pages.
+ */
+public class A11yMenuFooter {
+
+ /** Provides an interface for footer of a11yMenu. */
+ public interface A11yMenuFooterCallBack {
+
+ /** Calls back when user clicks the left button. */
+ void onLeftButtonClicked();
+
+ /** Calls back when user clicks the right button. */
+ void onRightButtonClicked();
+ }
+
+ private final FooterButtonClickListener mFooterButtonClickListener;
+
+ private ImageButton mPreviousPageBtn;
+ private ImageButton mNextPageBtn;
+ private View mTopListDivider;
+ private View mBottomListDivider;
+ private final A11yMenuFooterCallBack mCallBack;
+
+ public A11yMenuFooter(ViewGroup menuLayout, A11yMenuFooterCallBack callBack) {
+ this.mCallBack = callBack;
+ mFooterButtonClickListener = new FooterButtonClickListener();
+ configureFooterLayout(menuLayout);
+ }
+
+ public @Nullable ImageButton getPreviousPageBtn() {
+ return mPreviousPageBtn;
+ }
+
+ public @Nullable ImageButton getNextPageBtn() {
+ return mNextPageBtn;
+ }
+
+ private void configureFooterLayout(ViewGroup menuLayout) {
+ ViewGroup footerContainer = menuLayout.findViewById(R.id.footerlayout);
+ footerContainer.setVisibility(View.VISIBLE);
+
+ mPreviousPageBtn = menuLayout.findViewById(R.id.menu_prev_button);
+ mNextPageBtn = menuLayout.findViewById(R.id.menu_next_button);
+ mTopListDivider = menuLayout.findViewById(R.id.top_listDivider);
+ mBottomListDivider = menuLayout.findViewById(R.id.bottom_listDivider);
+
+ // Registers listeners for footer buttons.
+ setListener(mPreviousPageBtn);
+ setListener(mNextPageBtn);
+
+ menuLayout
+ .getViewTreeObserver()
+ .addOnGlobalLayoutListener(
+ new OnGlobalLayoutListener() {
+ @Override
+ public void onGlobalLayout() {
+ menuLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
+ expandBtnTouchArea(mPreviousPageBtn, menuLayout);
+ expandBtnTouchArea(mNextPageBtn, (View) mNextPageBtn.getParent());
+ }
+ });
+ }
+
+ private void expandBtnTouchArea(ImageButton btn, View btnParent) {
+ Rect btnRect = new Rect();
+ btn.getHitRect(btnRect);
+ btnRect.top -= getHitRectHeight(mTopListDivider);
+ btnRect.bottom += getHitRectHeight(mBottomListDivider);
+ btnParent.setTouchDelegate(new TouchDelegate(btnRect, btn));
+ }
+
+ private static int getHitRectHeight(View listDivider) {
+ Rect hitRect = new Rect();
+ listDivider.getHitRect(hitRect);
+ return hitRect.height();
+ }
+
+ private void setListener(@Nullable View view) {
+ if (view != null) {
+ view.setOnClickListener(mFooterButtonClickListener);
+ }
+ }
+
+ /** Handles click event for footer buttons. */
+ private class FooterButtonClickListener implements OnClickListener {
+ @Override
+ public void onClick(View view) {
+ if (view.getId() == R.id.menu_prev_button) {
+ mCallBack.onLeftButtonClicked();
+ } else if (view.getId() == R.id.menu_next_button) {
+ mCallBack.onRightButtonClicked();
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuOverlayLayout.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuOverlayLayout.java
new file mode 100644
index 0000000..740bc8a
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuOverlayLayout.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.accessibility.accessibilitymenu.view;
+
+import static java.lang.Math.max;
+
+import android.content.res.Configuration;
+import android.graphics.Insets;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.view.Display;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.Surface;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowInsets;
+import android.view.WindowManager;
+import android.view.WindowMetrics;
+import android.widget.FrameLayout;
+import android.widget.Toast;
+
+import com.android.systemui.accessibility.accessibilitymenu.AccessibilityMenuService;
+import com.android.systemui.accessibility.accessibilitymenu.R;
+import com.android.systemui.accessibility.accessibilitymenu.model.A11yMenuShortcut;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Provides functionality for Accessibility menu layout in a11y menu overlay. There are functions to
+ * configure or update Accessibility menu layout when orientation and display size changed, and
+ * functions to toggle menu visibility when button clicked or screen off.
+ */
+public class A11yMenuOverlayLayout {
+
+ /** Predefined default shortcuts when large button setting is off. */
+ private static final int[] SHORTCUT_LIST_DEFAULT = {
+ A11yMenuShortcut.ShortcutId.ID_ASSISTANT_VALUE.ordinal(),
+ A11yMenuShortcut.ShortcutId.ID_A11YSETTING_VALUE.ordinal(),
+ A11yMenuShortcut.ShortcutId.ID_POWER_VALUE.ordinal(),
+ A11yMenuShortcut.ShortcutId.ID_VOLUME_DOWN_VALUE.ordinal(),
+ A11yMenuShortcut.ShortcutId.ID_VOLUME_UP_VALUE.ordinal(),
+ A11yMenuShortcut.ShortcutId.ID_RECENT_VALUE.ordinal(),
+ A11yMenuShortcut.ShortcutId.ID_BRIGHTNESS_DOWN_VALUE.ordinal(),
+ A11yMenuShortcut.ShortcutId.ID_BRIGHTNESS_UP_VALUE.ordinal(),
+ A11yMenuShortcut.ShortcutId.ID_LOCKSCREEN_VALUE.ordinal(),
+ A11yMenuShortcut.ShortcutId.ID_QUICKSETTING_VALUE.ordinal(),
+ A11yMenuShortcut.ShortcutId.ID_NOTIFICATION_VALUE.ordinal(),
+ A11yMenuShortcut.ShortcutId.ID_SCREENSHOT_VALUE.ordinal()
+ };
+
+ private final AccessibilityMenuService mService;
+ private final WindowManager mWindowManager;
+ private ViewGroup mLayout;
+ private WindowManager.LayoutParams mLayoutParameter;
+ private A11yMenuViewPager mA11yMenuViewPager;
+
+ public A11yMenuOverlayLayout(AccessibilityMenuService service) {
+ mService = service;
+ mWindowManager = mService.getSystemService(WindowManager.class);
+ configureLayout();
+ }
+
+ /** Creates Accessibility menu layout and configure layout parameters. */
+ public View configureLayout() {
+ return configureLayout(A11yMenuViewPager.DEFAULT_PAGE_INDEX);
+ }
+
+ // TODO(b/78292783): Find a better way to inflate layout in the test.
+ /**
+ * Creates Accessibility menu layout, configure layout parameters and apply index to ViewPager.
+ *
+ * @param pageIndex the index of the ViewPager to show.
+ */
+ public View configureLayout(int pageIndex) {
+
+ int lastVisibilityState = View.GONE;
+ if (mLayout != null) {
+ lastVisibilityState = mLayout.getVisibility();
+ mWindowManager.removeView(mLayout);
+ mLayout = null;
+ }
+
+ if (mLayoutParameter == null) {
+ initLayoutParams();
+ }
+
+ mLayout = new FrameLayout(mService);
+ updateLayoutPosition();
+ inflateLayoutAndSetOnTouchListener(mLayout);
+ mA11yMenuViewPager = new A11yMenuViewPager(mService);
+ mA11yMenuViewPager.configureViewPagerAndFooter(mLayout, createShortcutList(), pageIndex);
+ mWindowManager.addView(mLayout, mLayoutParameter);
+ mLayout.setVisibility(lastVisibilityState);
+
+ return mLayout;
+ }
+
+ /** Updates view layout with new layout parameters only. */
+ public void updateViewLayout() {
+ if (mLayout == null || mLayoutParameter == null) {
+ return;
+ }
+ updateLayoutPosition();
+ mWindowManager.updateViewLayout(mLayout, mLayoutParameter);
+ }
+
+ private void initLayoutParams() {
+ mLayoutParameter = new WindowManager.LayoutParams();
+ mLayoutParameter.type = WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
+ mLayoutParameter.format = PixelFormat.TRANSLUCENT;
+ mLayoutParameter.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
+ mLayoutParameter.flags |= WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
+ mLayoutParameter.setTitle(mService.getString(R.string.accessibility_menu_service_name));
+ }
+
+ private void inflateLayoutAndSetOnTouchListener(ViewGroup view) {
+ LayoutInflater inflater = LayoutInflater.from(mService);
+ inflater.inflate(R.layout.paged_menu, view);
+ view.setOnTouchListener(mService);
+ }
+
+ /**
+ * Loads shortcut data from default shortcut ID array.
+ *
+ * @return A list of default shortcuts
+ */
+ private List<A11yMenuShortcut> createShortcutList() {
+ List<A11yMenuShortcut> shortcutList = new ArrayList<>();
+ for (int shortcutId : SHORTCUT_LIST_DEFAULT) {
+ shortcutList.add(new A11yMenuShortcut(shortcutId));
+ }
+ return shortcutList;
+ }
+
+ /** Updates a11y menu layout position by configuring layout params. */
+ private void updateLayoutPosition() {
+ Display display = mLayout.getDisplay();
+ final int orientation = mService.getResources().getConfiguration().orientation;
+ if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
+ switch (display.getRotation()) {
+ case Surface.ROTATION_90:
+ case Surface.ROTATION_180:
+ mLayoutParameter.gravity =
+ Gravity.END | Gravity.BOTTOM
+ | Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL;
+ mLayoutParameter.width = WindowManager.LayoutParams.WRAP_CONTENT;
+ mLayoutParameter.height = WindowManager.LayoutParams.MATCH_PARENT;
+ mLayoutParameter.flags |= WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
+ mLayoutParameter.flags |= WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
+ mLayout.setBackgroundResource(R.drawable.shadow_90deg);
+ break;
+ case Surface.ROTATION_0:
+ case Surface.ROTATION_270:
+ mLayoutParameter.gravity =
+ Gravity.START | Gravity.BOTTOM
+ | Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL;
+ mLayoutParameter.width = WindowManager.LayoutParams.WRAP_CONTENT;
+ mLayoutParameter.height = WindowManager.LayoutParams.MATCH_PARENT;
+ mLayoutParameter.flags |= WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
+ mLayoutParameter.flags |= WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
+ mLayout.setBackgroundResource(R.drawable.shadow_270deg);
+ break;
+ default:
+ break;
+ }
+ } else {
+ mLayoutParameter.gravity = Gravity.BOTTOM;
+ mLayoutParameter.width = WindowManager.LayoutParams.MATCH_PARENT;
+ mLayoutParameter.height = WindowManager.LayoutParams.WRAP_CONTENT;
+ mLayout.setBackgroundResource(R.drawable.shadow_0deg);
+ }
+
+ // Adjusts the y position of a11y menu layout to make the layout not to overlap bottom
+ // navigation bar window.
+ updateLayoutByWindowInsetsIfNeeded();
+ mLayout.setOnApplyWindowInsetsListener(
+ (view, insets) -> {
+ if (updateLayoutByWindowInsetsIfNeeded()) {
+ mWindowManager.updateViewLayout(mLayout, mLayoutParameter);
+ }
+ return view.onApplyWindowInsets(insets);
+ });
+ }
+
+ /**
+ * Returns {@code true} if the a11y menu layout params
+ * should be updated by {@link WindowManager} immediately due to window insets change.
+ * This method adjusts the layout position and size to
+ * make a11y menu not to overlap navigation bar window.
+ */
+ private boolean updateLayoutByWindowInsetsIfNeeded() {
+ boolean shouldUpdateLayout = false;
+ WindowMetrics windowMetrics = mWindowManager.getCurrentWindowMetrics();
+ Insets windowInsets = windowMetrics.getWindowInsets().getInsetsIgnoringVisibility(
+ WindowInsets.Type.systemBars() | WindowInsets.Type.displayCutout());
+ int xOffset = max(windowInsets.left, windowInsets.right);
+ int yOffset = windowInsets.bottom;
+ Rect windowBound = windowMetrics.getBounds();
+ if (mLayoutParameter.x != xOffset || mLayoutParameter.y != yOffset) {
+ mLayoutParameter.x = xOffset;
+ mLayoutParameter.y = yOffset;
+ shouldUpdateLayout = true;
+ }
+ // for gestural navigation mode and the landscape mode,
+ // the layout height should be decreased by system bar
+ // and display cutout inset to fit the new
+ // frame size that doesn't overlap the navigation bar window.
+ int orientation = mService.getResources().getConfiguration().orientation;
+ if (mLayout.getHeight() != mLayoutParameter.height
+ && orientation == Configuration.ORIENTATION_LANDSCAPE) {
+ mLayoutParameter.height = windowBound.height() - yOffset;
+ shouldUpdateLayout = true;
+ }
+ return shouldUpdateLayout;
+ }
+
+ /**
+ * Gets the current page index when device configuration changed. {@link
+ * AccessibilityMenuService#onConfigurationChanged(Configuration)}
+ *
+ * @return the current index of the ViewPager.
+ */
+ public int getPageIndex() {
+ if (mA11yMenuViewPager != null) {
+ return mA11yMenuViewPager.mViewPager.getCurrentItem();
+ }
+ return A11yMenuViewPager.DEFAULT_PAGE_INDEX;
+ }
+
+ /**
+ * Hides a11y menu layout. And return if layout visibility has been changed.
+ *
+ * @return {@code true} layout visibility is toggled off; {@code false} is unchanged
+ */
+ public boolean hideMenu() {
+ if (mLayout.getVisibility() == View.VISIBLE) {
+ mLayout.setVisibility(View.GONE);
+ return true;
+ }
+ return false;
+ }
+
+ /** Toggles a11y menu layout visibility. */
+ public void toggleVisibility() {
+ mLayout.setVisibility((mLayout.getVisibility() == View.VISIBLE) ? View.GONE : View.VISIBLE);
+ }
+
+ /** Shows hint text on Toast. */
+ public void showToast(String text) {
+ final View viewPos = mLayout.findViewById(R.id.coordinatorLayout);
+ Toast.makeText(viewPos.getContext(), text, Toast.LENGTH_SHORT).show();
+ }
+}
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuViewPager.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuViewPager.java
new file mode 100644
index 0000000..c510b87
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuViewPager.java
@@ -0,0 +1,356 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.accessibility.accessibilitymenu.view;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.graphics.Insets;
+import android.util.DisplayMetrics;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver.OnGlobalLayoutListener;
+import android.view.WindowInsets;
+import android.view.WindowManager;
+import android.view.WindowMetrics;
+import android.widget.GridView;
+
+import androidx.viewpager.widget.ViewPager;
+
+import com.android.systemui.accessibility.accessibilitymenu.AccessibilityMenuService;
+import com.android.systemui.accessibility.accessibilitymenu.R;
+import com.android.systemui.accessibility.accessibilitymenu.model.A11yMenuShortcut;
+import com.android.systemui.accessibility.accessibilitymenu.view.A11yMenuFooter.A11yMenuFooterCallBack;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class handles UI for viewPager and footer.
+ * It displays grid pages containing all shortcuts in viewPager,
+ * and handles the click events from footer to switch between pages.
+ */
+public class A11yMenuViewPager {
+
+ /** The default index of the ViewPager. */
+ public static final int DEFAULT_PAGE_INDEX = 0;
+
+ /**
+ * The class holds the static parameters for grid view when large button settings is on/off.
+ */
+ public static final class GridViewParams {
+ /** Total shortcuts count in the grid view when large button settings is off. */
+ public static final int GRID_ITEM_COUNT = 9;
+
+ /** The number of columns in the grid view when large button settings is off. */
+ public static final int GRID_COLUMN_COUNT = 3;
+
+ /** Total shortcuts count in the grid view when large button settings is on. */
+ public static final int LARGE_GRID_ITEM_COUNT = 4;
+
+ /** The number of columns in the grid view when large button settings is on. */
+ public static final int LARGE_GRID_COLUMN_COUNT = 2;
+
+ /** Temporary measure to test both item types. */
+ private static final boolean USE_LARGE_ITEMS = true;
+
+ /**
+ * Returns the number of items in the grid view.
+ *
+ * @param context The parent context
+ * @return Grid item count
+ */
+ public static int getGridItemCount(Context context) {
+ return USE_LARGE_ITEMS
+ ? LARGE_GRID_ITEM_COUNT
+ : GRID_ITEM_COUNT;
+ }
+
+ /**
+ * Returns the number of columns in the grid view.
+ *
+ * @param context The parent context
+ * @return Grid column count
+ */
+ public static int getGridColumnCount(Context context) {
+ return USE_LARGE_ITEMS
+ ? LARGE_GRID_COLUMN_COUNT
+ : GRID_COLUMN_COUNT;
+ }
+
+ /**
+ * Returns the number of rows in the grid view.
+ *
+ * @param context The parent context
+ * @return Grid row count
+ */
+ public static int getGridRowCount(Context context) {
+ return USE_LARGE_ITEMS
+ ? (LARGE_GRID_ITEM_COUNT / LARGE_GRID_COLUMN_COUNT)
+ : (GRID_ITEM_COUNT / GRID_COLUMN_COUNT);
+ }
+
+ /**
+ * Separates a provided list of accessibility shortcuts into multiple sub-lists.
+ * Does not modify the original list.
+ *
+ * @param pageItemCount The maximum size of an individual sub-list.
+ * @param shortcutList The list of shortcuts to be separated into sub-lists.
+ * @return A list of shortcut sub-lists.
+ */
+ public static List<List<A11yMenuShortcut>> generateShortcutSubLists(
+ int pageItemCount, List<A11yMenuShortcut> shortcutList) {
+ int start = 0;
+ int end;
+ int shortcutListSize = shortcutList.size();
+ List<List<A11yMenuShortcut>> subLists = new ArrayList<>();
+ while (start < shortcutListSize) {
+ end = Math.min(start + pageItemCount, shortcutListSize);
+ subLists.add(shortcutList.subList(start, end));
+ start = end;
+ }
+ return subLists;
+ }
+
+ private GridViewParams() {}
+ }
+
+ private final AccessibilityMenuService mService;
+
+ /**
+ * The pager widget, which handles animation and allows swiping horizontally to access previous
+ * and next gridView pages.
+ */
+ protected ViewPager mViewPager;
+
+ private ViewPagerAdapter<GridView> mViewPagerAdapter;
+ private final List<GridView> mGridPageList = new ArrayList<>();
+
+ /** The footer, which provides buttons to switch between pages */
+ protected A11yMenuFooter mA11yMenuFooter;
+
+ /** The shortcut list intended to show in grid pages of viewPager */
+ private List<A11yMenuShortcut> mA11yMenuShortcutList;
+
+ /** The container layout for a11y menu. */
+ private ViewGroup mA11yMenuLayout;
+
+ public A11yMenuViewPager(AccessibilityMenuService service) {
+ this.mService = service;
+ }
+
+ /**
+ * Configures UI for view pager and footer.
+ *
+ * @param a11yMenuLayout the container layout for a11y menu
+ * @param shortcutDataList the data list need to show in view pager
+ * @param pageIndex the index of ViewPager to show
+ */
+ public void configureViewPagerAndFooter(
+ ViewGroup a11yMenuLayout, List<A11yMenuShortcut> shortcutDataList, int pageIndex) {
+ this.mA11yMenuLayout = a11yMenuLayout;
+ mA11yMenuShortcutList = shortcutDataList;
+ initViewPager();
+ initChildPage();
+ mA11yMenuFooter = new A11yMenuFooter(a11yMenuLayout, mFooterCallbacks);
+ updateFooterState();
+ registerOnGlobalLayoutListener();
+ goToPage(pageIndex);
+ }
+
+ /** Initializes viewPager and its adapter. */
+ private void initViewPager() {
+ mViewPager = mA11yMenuLayout.findViewById(R.id.view_pager);
+ mViewPagerAdapter = new ViewPagerAdapter<>();
+ mViewPager.setAdapter(mViewPagerAdapter);
+ mViewPager.setOverScrollMode(View.OVER_SCROLL_NEVER);
+ mViewPager.addOnPageChangeListener(
+ new ViewPager.OnPageChangeListener() {
+ @Override
+ public void onPageScrollStateChanged(int state) {}
+
+ @Override
+ public void onPageScrolled(
+ int position, float positionOffset, int positionOffsetPixels) {}
+
+ @Override
+ public void onPageSelected(int position) {
+ updateFooterState();
+ }
+ });
+ }
+
+ /** Creates child pages of viewPager by the length of shortcuts and initializes them. */
+ private void initChildPage() {
+ if (mA11yMenuShortcutList == null || mA11yMenuShortcutList.isEmpty()) {
+ return;
+ }
+
+ if (!mGridPageList.isEmpty()) {
+ mGridPageList.clear();
+ }
+
+ // Generate pages by calculating # of items per grid.
+ for (List<A11yMenuShortcut> page : GridViewParams.generateShortcutSubLists(
+ GridViewParams.getGridItemCount(mService), mA11yMenuShortcutList)
+ ) {
+ addGridPage(page);
+ }
+
+ mViewPagerAdapter.set(mGridPageList);
+ }
+
+ private void addGridPage(List<A11yMenuShortcut> shortcutDataListInPage) {
+ LayoutInflater inflater = LayoutInflater.from(mService);
+ View view = inflater.inflate(R.layout.grid_view, null);
+ GridView gridView = view.findViewById(R.id.gridview);
+ A11yMenuAdapter adapter = new A11yMenuAdapter(mService, shortcutDataListInPage);
+ gridView.setNumColumns(GridViewParams.getGridColumnCount(mService));
+ gridView.setAdapter(adapter);
+ mGridPageList.add(gridView);
+ }
+
+ /** Updates footer's state by index of current page in view pager. */
+ private void updateFooterState() {
+ int currentPage = mViewPager.getCurrentItem();
+ int lastPage = mViewPager.getAdapter().getCount() - 1;
+ mA11yMenuFooter.getPreviousPageBtn().setEnabled(currentPage > 0);
+ mA11yMenuFooter.getNextPageBtn().setEnabled(currentPage < lastPage);
+ }
+
+ private void goToPage(int pageIndex) {
+ if (mViewPager == null) {
+ return;
+ }
+ if ((pageIndex >= 0) && (pageIndex < mViewPager.getAdapter().getCount())) {
+ mViewPager.setCurrentItem(pageIndex);
+ }
+ }
+
+ /** Registers OnGlobalLayoutListener to adjust menu UI by running callback at first time. */
+ private void registerOnGlobalLayoutListener() {
+ mA11yMenuLayout
+ .getViewTreeObserver()
+ .addOnGlobalLayoutListener(
+ new OnGlobalLayoutListener() {
+
+ boolean mIsFirstTime = true;
+
+ @Override
+ public void onGlobalLayout() {
+ if (!mIsFirstTime) {
+ return;
+ }
+
+ if (mGridPageList.isEmpty()) {
+ return;
+ }
+
+ GridView firstGridView = mGridPageList.get(0);
+ if (firstGridView == null
+ || firstGridView.getChildAt(0) == null) {
+ return;
+ }
+
+ mIsFirstTime = false;
+
+ int gridItemHeight = firstGridView.getChildAt(0)
+ .getMeasuredHeight();
+ adjustMenuUISize(gridItemHeight);
+ }
+ });
+ }
+
+ /**
+ * Adjusts menu UI to fit both landscape and portrait mode.
+ *
+ * <ol>
+ * <li>Adjust view pager's height.
+ * <li>Adjust vertical interval between grid items.
+ * <li>Adjust padding in view pager.
+ * </ol>
+ */
+ private void adjustMenuUISize(int gridItemHeight) {
+ final int rowsInGridView = GridViewParams.getGridRowCount(mService);
+ final int defaultMargin =
+ (int) mService.getResources().getDimension(R.dimen.a11ymenu_layout_margin);
+ final int topMargin = (int) mService.getResources().getDimension(R.dimen.table_margin_top);
+ final int displayMode = mService.getResources().getConfiguration().orientation;
+ int viewPagerHeight = mViewPager.getMeasuredHeight();
+
+ if (displayMode == Configuration.ORIENTATION_PORTRAIT) {
+ // In portrait mode, we only need to adjust view pager's height to match its
+ // child's height.
+ viewPagerHeight = gridItemHeight * rowsInGridView + defaultMargin + topMargin;
+ } else if (displayMode == Configuration.ORIENTATION_LANDSCAPE) {
+ // In landscape mode, we need to adjust view pager's height to match screen height
+ // and adjust its child too,
+ // because a11y menu layout height is limited by the screen height.
+ DisplayMetrics displayMetrics = mService.getResources().getDisplayMetrics();
+ float densityScale = (float) displayMetrics.densityDpi
+ / DisplayMetrics.DENSITY_DEVICE_STABLE;
+ View footerLayout = mA11yMenuLayout.findViewById(R.id.footerlayout);
+ // Keeps footer window height unchanged no matter the density is changed.
+ footerLayout.getLayoutParams().height =
+ (int) (footerLayout.getLayoutParams().height / densityScale);
+ // Adjust the view pager height for system bar and display cutout insets.
+ WindowManager windowManager = mService.getSystemService(WindowManager.class);
+ WindowMetrics windowMetric = windowManager.getCurrentWindowMetrics();
+ Insets windowInsets = windowMetric.getWindowInsets().getInsetsIgnoringVisibility(
+ WindowInsets.Type.systemBars() | WindowInsets.Type.displayCutout());
+ viewPagerHeight =
+ windowMetric.getBounds().height()
+ - footerLayout.getLayoutParams().height
+ - windowInsets.bottom;
+ // Sets vertical interval between grid items.
+ int interval =
+ (viewPagerHeight - topMargin - defaultMargin
+ - (rowsInGridView * gridItemHeight))
+ / (rowsInGridView + 1);
+ for (GridView gridView : mGridPageList) {
+ gridView.setVerticalSpacing(interval);
+ }
+
+ // Sets padding to view pager.
+ final int finalMarginTop = interval + topMargin;
+ mViewPager.setPadding(defaultMargin, finalMarginTop, defaultMargin, defaultMargin);
+ }
+ final ViewGroup.LayoutParams layoutParams = mViewPager.getLayoutParams();
+ layoutParams.height = viewPagerHeight;
+ mViewPager.setLayoutParams(layoutParams);
+ }
+
+ /** Callback object to handle click events from A11yMenuFooter */
+ protected A11yMenuFooterCallBack mFooterCallbacks =
+ new A11yMenuFooterCallBack() {
+ @Override
+ public void onLeftButtonClicked() {
+ // Moves to previous page.
+ int targetPage = mViewPager.getCurrentItem() - 1;
+ goToPage(targetPage);
+ updateFooterState();
+ }
+
+ @Override
+ public void onRightButtonClicked() {
+ // Moves to next page.
+ int targetPage = mViewPager.getCurrentItem() + 1;
+ goToPage(targetPage);
+ updateFooterState();
+ }
+ };
+}
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/ViewPagerAdapter.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/ViewPagerAdapter.java
new file mode 100644
index 0000000..5670d72
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/ViewPagerAdapter.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.accessibility.accessibilitymenu.view;
+
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.viewpager.widget.PagerAdapter;
+
+import java.util.List;
+
+/** The pager adapter, which provides the pages to the view pager widget. */
+class ViewPagerAdapter<T extends View> extends PagerAdapter {
+
+ /** The widget list in each page of view pager. */
+ private List<T> mWidgetList;
+
+ ViewPagerAdapter() {}
+
+ public void set(List<T> tList) {
+ mWidgetList = tList;
+ notifyDataSetChanged();
+ }
+
+ @Override
+ public int getCount() {
+ if (mWidgetList == null) {
+ return 0;
+ }
+ return mWidgetList.size();
+ }
+
+ @Override
+ public int getItemPosition(Object object) {
+ return POSITION_NONE;
+ }
+
+ @Override
+ public boolean isViewFromObject(View view, Object object) {
+ return view == object;
+ }
+
+ @Override
+ public Object instantiateItem(ViewGroup container, int position) {
+ if (mWidgetList == null) {
+ return null;
+ }
+ container.addView(mWidgetList.get(position));
+ return mWidgetList.get(position);
+ }
+
+ @Override
+ public void destroyItem(ViewGroup container, int position, Object object) {
+ container.removeView((View) object);
+ }
+}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
index a450d3a..9a9236b 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
@@ -791,13 +791,13 @@
// Move the drawing of the source in the overlay of this dialog, then animate. We trigger a
// one-off synchronization to make sure that this is done in sync between the two different
// windows.
+ controller.startDrawingInOverlayOf(decorView)
synchronizeNextDraw(
then = {
isSourceDrawnInDialog = true
maybeStartLaunchAnimation()
}
)
- controller.startDrawingInOverlayOf(decorView)
}
/**
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/FontInterpolator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/FontInterpolator.kt
index 2903288..3d341af 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/FontInterpolator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/FontInterpolator.kt
@@ -33,7 +33,9 @@
private const val FONT_ITALIC_ANIMATION_STEP = 0.1f
private const val FONT_ITALIC_DEFAULT_VALUE = 0f
-/** Provide interpolation of two fonts by adjusting font variation settings. */
+/**
+ * Provide interpolation of two fonts by adjusting font variation settings.
+ */
class FontInterpolator {
/**
@@ -59,14 +61,11 @@
var index: Int,
val sortedAxes: MutableList<FontVariationAxis>
) {
- constructor(
- font: Font,
- axes: List<FontVariationAxis>
- ) : this(
- font.sourceIdentifier,
- font.ttcIndex,
- axes.toMutableList().apply { sortBy { it.tag } }
- )
+ constructor(font: Font, axes: List<FontVariationAxis>) :
+ this(font.sourceIdentifier,
+ font.ttcIndex,
+ axes.toMutableList().apply { sortBy { it.tag } }
+ )
fun set(font: Font, axes: List<FontVariationAxis>) {
sourceId = font.sourceIdentifier
@@ -87,7 +86,9 @@
private val tmpInterpKey = InterpKey(null, null, 0f)
private val tmpVarFontKey = VarFontKey(0, 0, mutableListOf())
- /** Linear interpolate the font variation settings. */
+ /**
+ * Linear interpolate the font variation settings.
+ */
fun lerp(start: Font, end: Font, progress: Float): Font {
if (progress == 0f) {
return start
@@ -114,34 +115,27 @@
// this doesn't take much time since the variation axes is usually up to 5. If we need to
// support more number of axes, we may want to preprocess the font and store the sorted axes
// and also pre-fill the missing axes value with default value from 'fvar' table.
- val newAxes =
- lerp(startAxes, endAxes) { tag, startValue, endValue ->
- when (tag) {
- // TODO: Good to parse 'fvar' table for retrieving default value.
- TAG_WGHT ->
- adjustWeight(
- MathUtils.lerp(
+ val newAxes = lerp(startAxes, endAxes) { tag, startValue, endValue ->
+ when (tag) {
+ // TODO: Good to parse 'fvar' table for retrieving default value.
+ TAG_WGHT -> adjustWeight(
+ MathUtils.lerp(
startValue ?: FONT_WEIGHT_DEFAULT_VALUE,
endValue ?: FONT_WEIGHT_DEFAULT_VALUE,
- progress
- )
- )
- TAG_ITAL ->
- adjustItalic(
- MathUtils.lerp(
+ progress))
+ TAG_ITAL -> adjustItalic(
+ MathUtils.lerp(
startValue ?: FONT_ITALIC_DEFAULT_VALUE,
endValue ?: FONT_ITALIC_DEFAULT_VALUE,
- progress
- )
- )
- else -> {
- require(startValue != null && endValue != null) {
- "Unable to interpolate due to unknown default axes value : $tag"
- }
- MathUtils.lerp(startValue, endValue, progress)
+ progress))
+ else -> {
+ require(startValue != null && endValue != null) {
+ "Unable to interpolate due to unknown default axes value : $tag"
}
+ MathUtils.lerp(startValue, endValue, progress)
}
}
+ }
// Check if we already make font for this axes. This is typically happens if the animation
// happens backward.
@@ -155,7 +149,9 @@
// This is the first time to make the font for the axes. Build and store it to the cache.
// Font.Builder#build won't throw IOException since creating fonts from existing fonts will
// not do any IO work.
- val newFont = Font.Builder(start).setFontVariationSettings(newAxes.toTypedArray()).build()
+ val newFont = Font.Builder(start)
+ .setFontVariationSettings(newAxes.toTypedArray())
+ .build()
interpCache[InterpKey(start, end, progress)] = newFont
verFontCache[VarFontKey(start, newAxes)] = newFont
return newFont
@@ -177,28 +173,26 @@
val tagA = if (i < start.size) start[i].tag else null
val tagB = if (j < end.size) end[j].tag else null
- val comp =
- when {
- tagA == null -> 1
- tagB == null -> -1
- else -> tagA.compareTo(tagB)
- }
+ val comp = when {
+ tagA == null -> 1
+ tagB == null -> -1
+ else -> tagA.compareTo(tagB)
+ }
- val axis =
- when {
- comp == 0 -> {
- val v = filter(tagA!!, start[i++].styleValue, end[j++].styleValue)
- FontVariationAxis(tagA, v)
- }
- comp < 0 -> {
- val v = filter(tagA!!, start[i++].styleValue, null)
- FontVariationAxis(tagA, v)
- }
- else -> { // comp > 0
- val v = filter(tagB!!, null, end[j++].styleValue)
- FontVariationAxis(tagB, v)
- }
+ val axis = when {
+ comp == 0 -> {
+ val v = filter(tagA!!, start[i++].styleValue, end[j++].styleValue)
+ FontVariationAxis(tagA, v)
}
+ comp < 0 -> {
+ val v = filter(tagA!!, start[i++].styleValue, null)
+ FontVariationAxis(tagA, v)
+ }
+ else -> { // comp > 0
+ val v = filter(tagB!!, null, end[j++].styleValue)
+ FontVariationAxis(tagB, v)
+ }
+ }
result.add(axis)
}
@@ -208,21 +202,21 @@
// For the performance reasons, we animate weight with FONT_WEIGHT_ANIMATION_STEP. This helps
// Cache hit ratio in the Skia glyph cache.
private fun adjustWeight(value: Float) =
- coerceInWithStep(value, FONT_WEIGHT_MIN, FONT_WEIGHT_MAX, FONT_WEIGHT_ANIMATION_STEP)
+ coerceInWithStep(value, FONT_WEIGHT_MIN, FONT_WEIGHT_MAX, FONT_WEIGHT_ANIMATION_STEP)
// For the performance reasons, we animate italic with FONT_ITALIC_ANIMATION_STEP. This helps
// Cache hit ratio in the Skia glyph cache.
private fun adjustItalic(value: Float) =
- coerceInWithStep(value, FONT_ITALIC_MIN, FONT_ITALIC_MAX, FONT_ITALIC_ANIMATION_STEP)
+ coerceInWithStep(value, FONT_ITALIC_MIN, FONT_ITALIC_MAX, FONT_ITALIC_ANIMATION_STEP)
private fun coerceInWithStep(v: Float, min: Float, max: Float, step: Float) =
- (v.coerceIn(min, max) / step).toInt() * step
+ (v.coerceIn(min, max) / step).toInt() * step
companion object {
private val EMPTY_AXES = arrayOf<FontVariationAxis>()
// Returns true if given two font instance can be interpolated.
fun canInterpolate(start: Font, end: Font) =
- start.ttcIndex == end.ttcIndex && start.sourceIdentifier == end.sourceIdentifier
+ start.ttcIndex == end.ttcIndex && start.sourceIdentifier == end.sourceIdentifier
}
}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt
index 0028d13..dfac02d 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt
@@ -195,14 +195,16 @@
backgroundDrawable = WrappedDrawable(background)
backgroundView?.background = backgroundDrawable
+ // Delay the calls to `ghostedView.setVisibility()` during the animation. This must be
+ // called before `GhostView.addGhost()` is called because the latter will change the
+ // *transition* visibility, which won't be blocked and will affect the normal View
+ // visibility that is saved by `setShouldBlockVisibilityChanges()` for a later restoration.
+ (ghostedView as? LaunchableView)?.setShouldBlockVisibilityChanges(true)
+
// Create a ghost of the view that will be moving and fading out. This allows to fade out
// the content before fading out the background.
ghostView = GhostView.addGhost(ghostedView, launchContainer)
- // The ghost was just created, so ghostedView is currently invisible. We need to make sure
- // that it stays invisible as long as we are animating.
- (ghostedView as? LaunchableView)?.setShouldBlockVisibilityChanges(true)
-
val matrix = ghostView?.animationMatrix ?: Matrix.IDENTITY_MATRIX
matrix.getValues(initialGhostViewMatrixValues)
@@ -297,14 +299,19 @@
backgroundDrawable?.wrapped?.alpha = startBackgroundAlpha
GhostView.removeGhost(ghostedView)
- (ghostedView as? LaunchableView)?.setShouldBlockVisibilityChanges(false)
launchContainerOverlay.remove(backgroundView)
- // Make sure that the view is considered VISIBLE by accessibility by first making it
- // INVISIBLE then VISIBLE (see b/204944038#comment17 for more info).
- ghostedView.visibility = View.INVISIBLE
- ghostedView.visibility = View.VISIBLE
- ghostedView.invalidate()
+ if (ghostedView is LaunchableView) {
+ // Restore the ghosted view visibility.
+ ghostedView.setShouldBlockVisibilityChanges(false)
+ } else {
+ // Make the ghosted view visible. We ensure that the view is considered VISIBLE by
+ // accessibility by first making it INVISIBLE then VISIBLE (see b/204944038#comment17
+ // for more info).
+ ghostedView.visibility = View.INVISIBLE
+ ghostedView.visibility = View.VISIBLE
+ ghostedView.invalidate()
+ }
}
companion object {
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt
index 67b59e0..774255b 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt
@@ -21,15 +21,19 @@
/** A view that can expand/launch into an app or a dialog. */
interface LaunchableView {
/**
- * Set whether this view should block/postpone all visibility changes. This ensures that this
- * view:
+ * Set whether this view should block/postpone all calls to [View.setVisibility]. This ensures
+ * that this view:
* - remains invisible during the launch animation given that it is ghosted and already drawn
* somewhere else.
* - remains invisible as long as a dialog expanded from it is shown.
* - restores its expected visibility once the dialog expanded from it is dismissed.
*
- * Note that when this is set to true, both the [normal][android.view.View.setVisibility] and
- * [transition][android.view.View.setTransitionVisibility] visibility changes must be blocked.
+ * When `setShouldBlockVisibilityChanges(false)` is called, then visibility of the View should
+ * be restored to its expected value, i.e. it should have the visibility of the last call to
+ * `View.setVisibility()` that was made after `setShouldBlockVisibilityChanges(true)`, if any,
+ * or the original view visibility otherwise.
+ *
+ * Note that calls to [View.setTransitionVisibility] shouldn't be blocked.
*
* @param block whether we should block/postpone all calls to `setVisibility` and
* `setTransitionVisibility`.
@@ -46,27 +50,31 @@
* super.setVisibility(visibility).
*/
private val superSetVisibility: (Int) -> Unit,
-
- /**
- * The lambda that should set the actual transition visibility of [view], usually by calling
- * super.setTransitionVisibility(visibility).
- */
- private val superSetTransitionVisibility: (Int) -> Unit,
-) {
+) : LaunchableView {
private var blockVisibilityChanges = false
private var lastVisibility = view.visibility
/** Call this when [LaunchableView.setShouldBlockVisibilityChanges] is called. */
- fun setShouldBlockVisibilityChanges(block: Boolean) {
+ override fun setShouldBlockVisibilityChanges(block: Boolean) {
if (block == blockVisibilityChanges) {
return
}
blockVisibilityChanges = block
if (block) {
+ // Save the current visibility for later.
lastVisibility = view.visibility
} else {
- superSetVisibility(lastVisibility)
+ // Restore the visibility. To avoid accessibility issues, we change the visibility twice
+ // which makes sure that we trigger a visibility flag change (see b/204944038#comment17
+ // for more info).
+ if (lastVisibility == View.VISIBLE) {
+ superSetVisibility(View.INVISIBLE)
+ superSetVisibility(View.VISIBLE)
+ } else {
+ superSetVisibility(View.VISIBLE)
+ superSetVisibility(lastVisibility)
+ }
}
}
@@ -79,16 +87,4 @@
superSetVisibility(visibility)
}
-
- /** Call this when [View.setTransitionVisibility] is called. */
- fun setTransitionVisibility(visibility: Int) {
- if (blockVisibilityChanges) {
- // View.setTransitionVisibility just sets the visibility flag, so we don't have to save
- // the transition visibility separately from the normal visibility.
- lastVisibility = visibility
- return
- }
-
- superSetTransitionVisibility(visibility)
- }
}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt
index 65d6c83..5f1bb83 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt
@@ -36,7 +36,8 @@
* Currently this class can provide text style animation for text weight and text size. For example
* the simple view that draws text with animating text size is like as follows:
*
- * ```
+ * <pre>
+ * <code>
* class SimpleTextAnimation : View {
* @JvmOverloads constructor(...)
*
@@ -52,34 +53,39 @@
* animator.setTextStyle(-1 /* unchanged weight */, sizePx, animate)
* }
* }
- * ```
+ * </code>
+ * </pre>
*/
-class TextAnimator(layout: Layout, private val invalidateCallback: () -> Unit) {
+class TextAnimator(
+ layout: Layout,
+ private val invalidateCallback: () -> Unit
+) {
// Following two members are for mutable for testing purposes.
public var textInterpolator: TextInterpolator = TextInterpolator(layout)
- public var animator: ValueAnimator =
- ValueAnimator.ofFloat(1f).apply {
- duration = DEFAULT_ANIMATION_DURATION
- addUpdateListener {
- textInterpolator.progress = it.animatedValue as Float
- invalidateCallback()
- }
- addListener(
- object : AnimatorListenerAdapter() {
- override fun onAnimationEnd(animation: Animator?) {
- textInterpolator.rebase()
- }
- override fun onAnimationCancel(animation: Animator?) = textInterpolator.rebase()
- }
- )
+ public var animator: ValueAnimator = ValueAnimator.ofFloat(1f).apply {
+ duration = DEFAULT_ANIMATION_DURATION
+ addUpdateListener {
+ textInterpolator.progress = it.animatedValue as Float
+ invalidateCallback()
}
+ addListener(object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(animation: Animator?) {
+ textInterpolator.rebase()
+ }
+ override fun onAnimationCancel(animation: Animator?) = textInterpolator.rebase()
+ })
+ }
sealed class PositionedGlyph {
- /** Mutable X coordinate of the glyph position relative from drawing offset. */
+ /**
+ * Mutable X coordinate of the glyph position relative from drawing offset.
+ */
var x: Float = 0f
- /** Mutable Y coordinate of the glyph position relative from the baseline. */
+ /**
+ * Mutable Y coordinate of the glyph position relative from the baseline.
+ */
var y: Float = 0f
/**
@@ -90,29 +96,40 @@
/**
* Mutable text size of the glyph in pixels.
*/
- /** Mutable text size of the glyph in pixels. */
var textSize: Float = 0f
- /** Mutable color of the glyph. */
+ /**
+ * Mutable color of the glyph.
+ */
var color: Int = 0
- /** Immutable character offset in the text that the current font run start. */
+ /**
+ * Immutable character offset in the text that the current font run start.
+ */
abstract var runStart: Int
protected set
- /** Immutable run length of the font run. */
+ /**
+ * Immutable run length of the font run.
+ */
abstract var runLength: Int
protected set
- /** Immutable glyph index of the font run. */
+ /**
+ * Immutable glyph index of the font run.
+ */
abstract var glyphIndex: Int
protected set
- /** Immutable font instance for this font run. */
+ /**
+ * Immutable font instance for this font run.
+ */
abstract var font: Font
protected set
- /** Immutable glyph ID for this glyph. */
+ /**
+ * Immutable glyph ID for this glyph.
+ */
abstract var glyphId: Int
protected set
}
@@ -130,30 +147,30 @@
/**
* GlyphFilter applied just before drawing to canvas for tweaking positions and text size.
*
- * This callback is called for each glyphs just before drawing the glyphs. This function will be
- * called with the intrinsic position, size, color, glyph ID and font instance. You can mutate
- * the position, size and color for tweaking animations. Do not keep the reference of passed
- * glyph object. The interpolator reuses that object for avoiding object allocations.
+ * This callback is called for each glyphs just before drawing the glyphs. This function will
+ * be called with the intrinsic position, size, color, glyph ID and font instance. You can
+ * mutate the position, size and color for tweaking animations.
+ * Do not keep the reference of passed glyph object. The interpolator reuses that object for
+ * avoiding object allocations.
*
- * Details: The text is drawn with font run units. The font run is a text segment that draws
- * with the same font. The {@code runStart} and {@code runLimit} is a range of the font run in
- * the text that current glyph is in. Once the font run is determined, the system will convert
- * characters into glyph IDs. The {@code glyphId} is the glyph identifier in the font and {@code
- * glyphIndex} is the offset of the converted glyph array. Please note that the {@code
- * glyphIndex} is not a character index, because the character will not be converted to glyph
- * one-by-one. If there are ligatures including emoji sequence, etc, the glyph ID may be
+ * Details:
+ * The text is drawn with font run units. The font run is a text segment that draws with the
+ * same font. The {@code runStart} and {@code runLimit} is a range of the font run in the text
+ * that current glyph is in. Once the font run is determined, the system will convert characters
+ * into glyph IDs. The {@code glyphId} is the glyph identifier in the font and
+ * {@code glyphIndex} is the offset of the converted glyph array. Please note that the
+ * {@code glyphIndex} is not a character index, because the character will not be converted to
+ * glyph one-by-one. If there are ligatures including emoji sequence, etc, the glyph ID may be
* composed from multiple characters.
*
* Here is an example of font runs: "fin. 終わり"
*
- * ```
* Characters : f i n . _ 終 わ り
* Code Points: \u0066 \u0069 \u006E \u002E \u0020 \u7D42 \u308F \u308A
* Font Runs : <-- Roboto-Regular.ttf --><-- NotoSans-CJK.otf -->
* runStart = 0, runLength = 5 runStart = 5, runLength = 3
* Glyph IDs : 194 48 7 8 4367 1039 1002
* Glyph Index: 0 1 2 3 0 1 2
- * ```
*
* In this example, the "fi" is converted into ligature form, thus the single glyph ID is
* assigned for two characters, f and i.
@@ -176,29 +193,28 @@
*/
var glyphFilter: GlyphCallback?
get() = textInterpolator.glyphFilter
- set(value) {
- textInterpolator.glyphFilter = value
- }
+ set(value) { textInterpolator.glyphFilter = value }
fun draw(c: Canvas) = textInterpolator.draw(c)
/**
* Set text style with animation.
*
- * By passing -1 to weight, the view preserve the current weight. By passing -1 to textSize, the
- * view preserve the current text size. Bu passing -1 to duration, the default text animation,
- * 1000ms, is used. By passing false to animate, the text will be updated without animation.
+ * By passing -1 to weight, the view preserve the current weight.
+ * By passing -1 to textSize, the view preserve the current text size.
+ * Bu passing -1 to duration, the default text animation, 1000ms, is used.
+ * By passing false to animate, the text will be updated without animation.
*
* @param weight an optional text weight.
* @param textSize an optional font size.
- * @param colors an optional colors array that must be the same size as numLines passed to the
- * TextInterpolator
+ * @param colors an optional colors array that must be the same size as numLines passed to
+ * the TextInterpolator
* @param animate an optional boolean indicating true for showing style transition as animation,
- * false for immediate style transition. True by default.
+ * false for immediate style transition. True by default.
* @param duration an optional animation duration in milliseconds. This is ignored if animate is
- * false.
+ * false.
* @param interpolator an optional time interpolator. If null is passed, last set interpolator
- * will be used. This is ignored if animate is false.
+ * will be used. This is ignored if animate is false.
*/
fun setTextStyle(
weight: Int = -1,
@@ -221,11 +237,10 @@
if (weight >= 0) {
// Paint#setFontVariationSettings creates Typeface instance from scratch. To reduce the
// memory impact, cache the typeface result.
- textInterpolator.targetPaint.typeface =
- typefaceCache.getOrElse(weight) {
- textInterpolator.targetPaint.fontVariationSettings = "'$TAG_WGHT' $weight"
- textInterpolator.targetPaint.typeface
- }
+ textInterpolator.targetPaint.typeface = typefaceCache.getOrElse(weight) {
+ textInterpolator.targetPaint.fontVariationSettings = "'$TAG_WGHT' $weight"
+ textInterpolator.targetPaint.typeface
+ }
}
if (color != null) {
textInterpolator.targetPaint.color = color
@@ -234,24 +249,22 @@
if (animate) {
animator.startDelay = delay
- animator.duration =
- if (duration == -1L) {
- DEFAULT_ANIMATION_DURATION
- } else {
- duration
- }
+ animator.duration = if (duration == -1L) {
+ DEFAULT_ANIMATION_DURATION
+ } else {
+ duration
+ }
interpolator?.let { animator.interpolator = it }
if (onAnimationEnd != null) {
- val listener =
- object : AnimatorListenerAdapter() {
- override fun onAnimationEnd(animation: Animator?) {
- onAnimationEnd.run()
- animator.removeListener(this)
- }
- override fun onAnimationCancel(animation: Animator?) {
- animator.removeListener(this)
- }
+ val listener = object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(animation: Animator?) {
+ onAnimationEnd.run()
+ animator.removeListener(this)
}
+ override fun onAnimationCancel(animation: Animator?) {
+ animator.removeListener(this)
+ }
+ }
animator.addListener(listener)
}
animator.start()
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt
index f9fb42c..0448c81 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt
@@ -26,8 +26,12 @@
import com.android.internal.graphics.ColorUtils
import java.lang.Math.max
-/** Provide text style linear interpolation for plain text. */
-class TextInterpolator(layout: Layout) {
+/**
+ * Provide text style linear interpolation for plain text.
+ */
+class TextInterpolator(
+ layout: Layout
+) {
/**
* Returns base paint used for interpolation.
@@ -60,11 +64,12 @@
var baseFont: Font,
var targetFont: Font
) {
- val length: Int
- get() = end - start
+ val length: Int get() = end - start
}
- /** A class represents text layout of a single run. */
+ /**
+ * A class represents text layout of a single run.
+ */
private class Run(
val glyphIds: IntArray,
val baseX: FloatArray, // same length as glyphIds
@@ -74,8 +79,12 @@
val fontRuns: List<FontRun>
)
- /** A class represents text layout of a single line. */
- private class Line(val runs: List<Run>)
+ /**
+ * A class represents text layout of a single line.
+ */
+ private class Line(
+ val runs: List<Run>
+ )
private var lines = listOf<Line>()
private val fontInterpolator = FontInterpolator()
@@ -97,8 +106,8 @@
/**
* The layout used for drawing text.
*
- * Only non-styled text is supported. Even if the given layout is created from Spanned, the span
- * information is not used.
+ * Only non-styled text is supported. Even if the given layout is created from Spanned, the
+ * span information is not used.
*
* The paint objects used for interpolation are not changed by this method call.
*
@@ -121,8 +130,8 @@
/**
* Recalculate internal text layout for interpolation.
*
- * Whenever the target paint is modified, call this method to recalculate internal text layout
- * used for interpolation.
+ * Whenever the target paint is modified, call this method to recalculate internal
+ * text layout used for interpolation.
*/
fun onTargetPaintModified() {
updatePositionsAndFonts(shapeText(layout, targetPaint), updateBase = false)
@@ -131,8 +140,8 @@
/**
* Recalculate internal text layout for interpolation.
*
- * Whenever the base paint is modified, call this method to recalculate internal text layout
- * used for interpolation.
+ * Whenever the base paint is modified, call this method to recalculate internal
+ * text layout used for interpolation.
*/
fun onBasePaintModified() {
updatePositionsAndFonts(shapeText(layout, basePaint), updateBase = true)
@@ -143,11 +152,11 @@
*
* The text interpolator does not calculate all the text position by text shaper due to
* performance reasons. Instead, the text interpolator shape the start and end state and
- * calculate text position of the middle state by linear interpolation. Due to this trick, the
- * text positions of the middle state is likely different from the text shaper result. So, if
- * you want to start animation from the middle state, you will see the glyph jumps due to this
- * trick, i.e. the progress 0.5 of interpolation between weight 400 and 700 is different from
- * text shape result of weight 550.
+ * calculate text position of the middle state by linear interpolation. Due to this trick,
+ * the text positions of the middle state is likely different from the text shaper result.
+ * So, if you want to start animation from the middle state, you will see the glyph jumps due to
+ * this trick, i.e. the progress 0.5 of interpolation between weight 400 and 700 is different
+ * from text shape result of weight 550.
*
* After calling this method, do not call onBasePaintModified() since it reshape the text and
* update the base state. As in above notice, the text shaping result at current progress is
@@ -159,7 +168,8 @@
* animate weight from 200 to 400, then if you want to move back to 200 at the half of the
* animation, it will look like
*
- * ```
+ * <pre>
+ * <code>
* val interp = TextInterpolator(layout)
*
* // Interpolate between weight 200 to 400.
@@ -189,7 +199,9 @@
* // progress is 0.5
* animator.start()
* }
- * ```
+ * </code>
+ * </pre>
+ *
*/
fun rebase() {
if (progress == 0f) {
@@ -251,75 +263,69 @@
}
var maxRunLength = 0
- lines =
- baseLayout.zip(targetLayout) { baseLine, targetLine ->
- val runs =
- baseLine.zip(targetLine) { base, target ->
- require(base.glyphCount() == target.glyphCount()) {
- "Inconsistent glyph count at line ${lines.size}"
+ lines = baseLayout.zip(targetLayout) { baseLine, targetLine ->
+ val runs = baseLine.zip(targetLine) { base, target ->
+
+ require(base.glyphCount() == target.glyphCount()) {
+ "Inconsistent glyph count at line ${lines.size}"
+ }
+
+ val glyphCount = base.glyphCount()
+
+ // Good to recycle the array if the existing array can hold the new layout result.
+ val glyphIds = IntArray(glyphCount) {
+ base.getGlyphId(it).also { baseGlyphId ->
+ require(baseGlyphId == target.getGlyphId(it)) {
+ "Inconsistent glyph ID at $it in line ${lines.size}"
}
+ }
+ }
- val glyphCount = base.glyphCount()
+ val baseX = FloatArray(glyphCount) { base.getGlyphX(it) }
+ val baseY = FloatArray(glyphCount) { base.getGlyphY(it) }
+ val targetX = FloatArray(glyphCount) { target.getGlyphX(it) }
+ val targetY = FloatArray(glyphCount) { target.getGlyphY(it) }
- // Good to recycle the array if the existing array can hold the new layout
- // result.
- val glyphIds =
- IntArray(glyphCount) {
- base.getGlyphId(it).also { baseGlyphId ->
- require(baseGlyphId == target.getGlyphId(it)) {
- "Inconsistent glyph ID at $it in line ${lines.size}"
- }
- }
+ // Calculate font runs
+ val fontRun = mutableListOf<FontRun>()
+ if (glyphCount != 0) {
+ var start = 0
+ var baseFont = base.getFont(start)
+ var targetFont = target.getFont(start)
+ require(FontInterpolator.canInterpolate(baseFont, targetFont)) {
+ "Cannot interpolate font at $start ($baseFont vs $targetFont)"
+ }
+
+ for (i in 1 until glyphCount) {
+ val nextBaseFont = base.getFont(i)
+ val nextTargetFont = target.getFont(i)
+
+ if (baseFont !== nextBaseFont) {
+ require(targetFont !== nextTargetFont) {
+ "Base font has changed at $i but target font has not changed."
}
-
- val baseX = FloatArray(glyphCount) { base.getGlyphX(it) }
- val baseY = FloatArray(glyphCount) { base.getGlyphY(it) }
- val targetX = FloatArray(glyphCount) { target.getGlyphX(it) }
- val targetY = FloatArray(glyphCount) { target.getGlyphY(it) }
-
- // Calculate font runs
- val fontRun = mutableListOf<FontRun>()
- if (glyphCount != 0) {
- var start = 0
- var baseFont = base.getFont(start)
- var targetFont = target.getFont(start)
+ // Font transition point. push run and reset context.
+ fontRun.add(FontRun(start, i, baseFont, targetFont))
+ maxRunLength = max(maxRunLength, i - start)
+ baseFont = nextBaseFont
+ targetFont = nextTargetFont
+ start = i
require(FontInterpolator.canInterpolate(baseFont, targetFont)) {
"Cannot interpolate font at $start ($baseFont vs $targetFont)"
}
-
- for (i in 1 until glyphCount) {
- val nextBaseFont = base.getFont(i)
- val nextTargetFont = target.getFont(i)
-
- if (baseFont !== nextBaseFont) {
- require(targetFont !== nextTargetFont) {
- "Base font has changed at $i but target font has not " +
- "changed."
- }
- // Font transition point. push run and reset context.
- fontRun.add(FontRun(start, i, baseFont, targetFont))
- maxRunLength = max(maxRunLength, i - start)
- baseFont = nextBaseFont
- targetFont = nextTargetFont
- start = i
- require(FontInterpolator.canInterpolate(baseFont, targetFont)) {
- "Cannot interpolate font at $start ($baseFont vs " +
- "$targetFont)"
- }
- } else { // baseFont === nextBaseFont
- require(targetFont === nextTargetFont) {
- "Base font has not changed at $i but target font has " +
- "changed."
- }
- }
+ } else { // baseFont === nextBaseFont
+ require(targetFont === nextTargetFont) {
+ "Base font has not changed at $i but target font has changed."
}
- fontRun.add(FontRun(start, glyphCount, baseFont, targetFont))
- maxRunLength = max(maxRunLength, glyphCount - start)
}
- Run(glyphIds, baseX, baseY, targetX, targetY, fontRun)
}
- Line(runs)
+ fontRun.add(FontRun(start, glyphCount, baseFont, targetFont))
+ maxRunLength = max(maxRunLength, glyphCount - start)
+ }
+ Run(glyphIds, baseX, baseY, targetX, targetY, fontRun)
}
+ Line(runs)
+ }
// Update float array used for drawing.
if (tmpPositionArray.size < maxRunLength * 2) {
@@ -351,9 +357,9 @@
if (glyphFilter == null) {
for (i in run.start until run.end) {
tmpPositionArray[arrayIndex++] =
- MathUtils.lerp(line.baseX[i], line.targetX[i], progress)
+ MathUtils.lerp(line.baseX[i], line.targetX[i], progress)
tmpPositionArray[arrayIndex++] =
- MathUtils.lerp(line.baseY[i], line.targetY[i], progress)
+ MathUtils.lerp(line.baseY[i], line.targetY[i], progress)
}
c.drawGlyphs(line.glyphIds, run.start, tmpPositionArray, 0, run.length, font, paint)
return
@@ -382,14 +388,13 @@
tmpPaintForGlyph.color = tmpGlyph.color
c.drawGlyphs(
- line.glyphIds,
- prevStart,
- tmpPositionArray,
- 0,
- i - prevStart,
- font,
- tmpPaintForGlyph
- )
+ line.glyphIds,
+ prevStart,
+ tmpPositionArray,
+ 0,
+ i - prevStart,
+ font,
+ tmpPaintForGlyph)
prevStart = i
arrayIndex = 0
}
@@ -399,14 +404,13 @@
}
c.drawGlyphs(
- line.glyphIds,
- prevStart,
- tmpPositionArray,
- 0,
- run.end - prevStart,
- font,
- tmpPaintForGlyph
- )
+ line.glyphIds,
+ prevStart,
+ tmpPositionArray,
+ 0,
+ run.end - prevStart,
+ font,
+ tmpPaintForGlyph)
}
private fun updatePositionsAndFonts(
@@ -414,7 +418,9 @@
updateBase: Boolean
) {
// Update target positions with newly calculated text layout.
- check(layoutResult.size == lines.size) { "The new layout result has different line count." }
+ check(layoutResult.size == lines.size) {
+ "The new layout result has different line count."
+ }
lines.zip(layoutResult) { line, runs ->
line.runs.zip(runs) { lineRun, newGlyphs ->
@@ -430,7 +436,7 @@
}
require(newFont === newGlyphs.getFont(i)) {
"The new layout has different font run." +
- " $newFont vs ${newGlyphs.getFont(i)} at $i"
+ " $newFont vs ${newGlyphs.getFont(i)} at $i"
}
}
@@ -438,7 +444,7 @@
// check new font can be interpolatable with base font.
require(FontInterpolator.canInterpolate(newFont, run.baseFont)) {
"New font cannot be interpolated with existing font. $newFont," +
- " ${run.baseFont}"
+ " ${run.baseFont}"
}
if (updateBase) {
@@ -474,7 +480,10 @@
}
// Shape the text and stores the result to out argument.
- private fun shapeText(layout: Layout, paint: TextPaint): List<List<PositionedGlyphs>> {
+ private fun shapeText(
+ layout: Layout,
+ paint: TextPaint
+ ): List<List<PositionedGlyphs>> {
val out = mutableListOf<List<PositionedGlyphs>>()
for (lineNo in 0 until layout.lineCount) { // Shape all lines.
val lineStart = layout.getLineStart(lineNo)
@@ -486,13 +495,10 @@
}
val runs = mutableListOf<PositionedGlyphs>()
- TextShaper.shapeText(
- layout.text,
- lineStart,
- count,
- layout.textDirectionHeuristic,
- paint
- ) { _, _, glyphs, _ -> runs.add(glyphs) }
+ TextShaper.shapeText(layout.text, lineStart, count, layout.textDirectionHeuristic,
+ paint) { _, _, glyphs, _ ->
+ runs.add(glyphs)
+ }
out.add(runs)
}
return out
@@ -500,8 +506,8 @@
}
private fun Layout.getDrawOrigin(lineNo: Int) =
- if (getParagraphDirection(lineNo) == Layout.DIR_LEFT_TO_RIGHT) {
- getLineLeft(lineNo)
- } else {
- getLineRight(lineNo)
- }
+ if (getParagraphDirection(lineNo) == Layout.DIR_LEFT_TO_RIGHT) {
+ getLineLeft(lineNo)
+ } else {
+ getLineRight(lineNo)
+ }
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ViewDialogLaunchAnimatorController.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ViewDialogLaunchAnimatorController.kt
index 964ef8c..46d5a5c 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ViewDialogLaunchAnimatorController.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ViewDialogLaunchAnimatorController.kt
@@ -34,23 +34,29 @@
override val sourceIdentity: Any = source
override fun startDrawingInOverlayOf(viewGroup: ViewGroup) {
+ // Delay the calls to `source.setVisibility()` during the animation. This must be called
+ // before `GhostView.addGhost()` is called because the latter will change the *transition*
+ // visibility, which won't be blocked and will affect the normal View visibility that is
+ // saved by `setShouldBlockVisibilityChanges()` for a later restoration.
+ (source as? LaunchableView)?.setShouldBlockVisibilityChanges(true)
+
// Create a temporary ghost of the source (which will make it invisible) and add it
// to the host dialog.
GhostView.addGhost(source, viewGroup)
-
- // The ghost of the source was just created, so the source is currently invisible.
- // We need to make sure that it stays invisible as long as the dialog is shown or
- // animating.
- (source as? LaunchableView)?.setShouldBlockVisibilityChanges(true)
}
override fun stopDrawingInOverlay() {
// Note: here we should remove the ghost from the overlay, but in practice this is
- // already done by the launch controllers created below.
+ // already done by the launch controller created below.
- // Make sure we allow the source to change its visibility again.
- (source as? LaunchableView)?.setShouldBlockVisibilityChanges(false)
- source.visibility = View.VISIBLE
+ if (source is LaunchableView) {
+ // Make sure we allow the source to change its visibility again and restore its previous
+ // value.
+ source.setShouldBlockVisibilityChanges(false)
+ } else {
+ // We made the source invisible earlier, so let's make it visible again.
+ source.visibility = View.VISIBLE
+ }
}
override fun createLaunchController(): LaunchAnimator.Controller {
@@ -67,10 +73,14 @@
override fun onLaunchAnimationEnd(isExpandingFullyAbove: Boolean) {
delegate.onLaunchAnimationEnd(isExpandingFullyAbove)
- // We hide the source when the dialog is showing. We will make this view
- // visible again when dismissing the dialog. This does nothing if the source
- // implements [LaunchableView], as it's already INVISIBLE in that case.
- source.visibility = View.INVISIBLE
+ // At this point the view visibility is restored by the delegate, so we delay the
+ // visibility changes again and make it invisible while the dialog is shown.
+ if (source is LaunchableView) {
+ source.setShouldBlockVisibilityChanges(true)
+ source.setTransitionVisibility(View.INVISIBLE)
+ } else {
+ source.visibility = View.INVISIBLE
+ }
}
}
}
@@ -90,13 +100,15 @@
}
override fun onExitAnimationCancelled() {
- // Make sure we allow the source to change its visibility again.
- (source as? LaunchableView)?.setShouldBlockVisibilityChanges(false)
-
- // If the view is invisible it's probably because of us, so we make it visible
- // again.
- if (source.visibility == View.INVISIBLE) {
- source.visibility = View.VISIBLE
+ if (source is LaunchableView) {
+ // Make sure we allow the source to change its visibility again.
+ source.setShouldBlockVisibilityChanges(false)
+ } else {
+ // If the view is invisible it's probably because of us, so we make it visible
+ // again.
+ if (source.visibility == View.INVISIBLE) {
+ source.visibility = View.VISIBLE
+ }
}
}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt
index 6715951..79bc2f4 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt
@@ -57,7 +57,7 @@
val onAnimationEnd: Runnable? = null
) {
companion object {
- const val DEFAULT_MAX_DURATION_IN_MILLIS = 7500f
+ const val DEFAULT_MAX_DURATION_IN_MILLIS = 30_000f // Max 30 sec
const val DEFAULT_EASING_DURATION_IN_MILLIS = 750f
const val DEFAULT_LUMINOSITY_MULTIPLIER = 1f
const val DEFAULT_NOISE_GRID_COUNT = 1.2f
diff --git a/packages/SystemUI/checks/Android.bp b/packages/SystemUI/checks/Android.bp
index 40580d2..d3f66e3 100644
--- a/packages/SystemUI/checks/Android.bp
+++ b/packages/SystemUI/checks/Android.bp
@@ -37,12 +37,6 @@
java_test_host {
name: "SystemUILintCheckerTest",
- // TODO(b/239881504): Since this test was written, Android
- // Lint was updated, and now includes classes that were
- // compiled for java 15. The soong build doesn't support
- // java 15 yet, so we can't compile against "lint". Disable
- // the test until java 15 is supported.
- enabled: false,
srcs: [
"tests/**/*.kt",
"tests/**/*.java",
@@ -59,5 +53,19 @@
],
test_options: {
unit_test: true,
+ tradefed_options: [
+ {
+ // lint bundles in some classes that were built with older versions
+ // of libraries, and no longer load. Since tradefed tries to load
+ // all classes in the jar to look for tests, it crashes loading them.
+ // Exclude these classes from tradefed's search.
+ name: "exclude-paths",
+ value: "org/apache",
+ },
+ {
+ name: "exclude-paths",
+ value: "META-INF",
+ },
+ ],
},
}
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt b/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt
index 259f0ed..4e96dda 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt
@@ -41,6 +41,7 @@
import androidx.compose.runtime.State
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
+import androidx.compose.runtime.movableContentOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCompositionContext
@@ -73,6 +74,7 @@
import androidx.compose.ui.unit.dp
import androidx.lifecycle.ViewTreeLifecycleOwner
import androidx.lifecycle.ViewTreeViewModelStoreOwner
+import com.android.compose.runtime.movableContentOf
import com.android.systemui.animation.Expandable
import com.android.systemui.animation.LaunchAnimator
import kotlin.math.max
@@ -170,25 +172,25 @@
val contentColor = controller.contentColor
val shape = controller.shape
- // TODO(b/230830644): Use movableContentOf to preserve the content state instead once the
- // Compose libraries have been updated and include aosp/2163631.
val wrappedContent =
- @Composable { controller: ExpandableController ->
- CompositionLocalProvider(
- LocalContentColor provides contentColor,
- ) {
- // We make sure that the content itself (wrapped by the background) is at least
- // 40.dp, which is the same as the M3 buttons. This applies even if onClick is
- // null, to make it easier to write expandables that are sometimes clickable and
- // sometimes not. There shouldn't be any Expandable smaller than 40dp because if
- // the expandable is not clickable directly, then something in its content should
- // be (and with a size >= 40dp).
- val minSize = 40.dp
- Box(
- Modifier.defaultMinSize(minWidth = minSize, minHeight = minSize),
- contentAlignment = Alignment.Center,
+ remember(content) {
+ movableContentOf { expandable: Expandable ->
+ CompositionLocalProvider(
+ LocalContentColor provides contentColor,
) {
- content(controller.expandable)
+ // We make sure that the content itself (wrapped by the background) is at least
+ // 40.dp, which is the same as the M3 buttons. This applies even if onClick is
+ // null, to make it easier to write expandables that are sometimes clickable and
+ // sometimes not. There shouldn't be any Expandable smaller than 40dp because if
+ // the expandable is not clickable directly, then something in its content
+ // should be (and with a size >= 40dp).
+ val minSize = 40.dp
+ Box(
+ Modifier.defaultMinSize(minWidth = minSize, minHeight = minSize),
+ contentAlignment = Alignment.Center,
+ ) {
+ content(expandable)
+ }
}
}
}
@@ -270,7 +272,7 @@
.onGloballyPositioned {
controller.boundsInComposeViewRoot.value = it.boundsInRoot()
}
- ) { wrappedContent(controller) }
+ ) { wrappedContent(controller.expandable) }
}
else -> {
val clickModifier =
@@ -301,7 +303,7 @@
controller.boundsInComposeViewRoot.value = it.boundsInRoot()
},
) {
- wrappedContent(controller)
+ wrappedContent(controller.expandable)
}
}
}
@@ -315,7 +317,7 @@
animatorState: State<LaunchAnimator.State?>,
overlay: ViewGroupOverlay,
controller: ExpandableControllerImpl,
- content: @Composable (ExpandableController) -> Unit,
+ content: @Composable (Expandable) -> Unit,
composeViewRoot: View,
onOverlayComposeViewChanged: (View?) -> Unit,
density: Density,
@@ -370,7 +372,7 @@
// We center the content in the expanding container.
contentAlignment = Alignment.Center,
) {
- Box(contentModifier) { content(controller) }
+ Box(contentModifier) { content(controller.expandable) }
}
}
}
diff --git a/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/compose/ComposeFacade.kt b/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/compose/ComposeFacade.kt
index 6e728ce..e253fb9 100644
--- a/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/compose/ComposeFacade.kt
+++ b/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/compose/ComposeFacade.kt
@@ -17,13 +17,21 @@
package com.android.systemui.compose
+import android.content.Context
+import android.view.View
import androidx.activity.ComponentActivity
+import androidx.lifecycle.LifecycleOwner
import com.android.systemui.people.ui.viewmodel.PeopleViewModel
+import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
/** The Compose facade, when Compose is *not* available. */
object ComposeFacade : BaseComposeFacade {
override fun isComposeAvailable(): Boolean = false
+ override fun composeInitializer(): ComposeInitializer {
+ throwComposeUnavailableError()
+ }
+
override fun setPeopleSpaceActivityContent(
activity: ComponentActivity,
viewModel: PeopleViewModel,
@@ -32,7 +40,15 @@
throwComposeUnavailableError()
}
- private fun throwComposeUnavailableError() {
+ override fun createFooterActionsView(
+ context: Context,
+ viewModel: FooterActionsViewModel,
+ qsVisibilityLifecycleOwner: LifecycleOwner
+ ): View {
+ throwComposeUnavailableError()
+ }
+
+ private fun throwComposeUnavailableError(): Nothing {
error(
"Compose is not available. Make sure to check isComposeAvailable() before calling any" +
" other function on ComposeFacade."
diff --git a/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeFacade.kt b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeFacade.kt
index 6991ff8..1ea18fe 100644
--- a/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeFacade.kt
+++ b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeFacade.kt
@@ -16,16 +16,24 @@
package com.android.systemui.compose
+import android.content.Context
+import android.view.View
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
+import androidx.compose.ui.platform.ComposeView
+import androidx.lifecycle.LifecycleOwner
import com.android.compose.theme.PlatformTheme
import com.android.systemui.people.ui.compose.PeopleScreen
import com.android.systemui.people.ui.viewmodel.PeopleViewModel
+import com.android.systemui.qs.footer.ui.compose.FooterActions
+import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
/** The Compose facade, when Compose is available. */
object ComposeFacade : BaseComposeFacade {
override fun isComposeAvailable(): Boolean = true
+ override fun composeInitializer(): ComposeInitializer = ComposeInitializerImpl
+
override fun setPeopleSpaceActivityContent(
activity: ComponentActivity,
viewModel: PeopleViewModel,
@@ -33,4 +41,14 @@
) {
activity.setContent { PlatformTheme { PeopleScreen(viewModel, onResult) } }
}
+
+ override fun createFooterActionsView(
+ context: Context,
+ viewModel: FooterActionsViewModel,
+ qsVisibilityLifecycleOwner: LifecycleOwner,
+ ): View {
+ return ComposeView(context).apply {
+ setContent { PlatformTheme { FooterActions(viewModel, qsVisibilityLifecycleOwner) } }
+ }
+ }
}
diff --git a/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeInitializerImpl.kt b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeInitializerImpl.kt
new file mode 100644
index 0000000..772c891
--- /dev/null
+++ b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeInitializerImpl.kt
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.compose
+
+import android.view.View
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.ViewTreeLifecycleOwner
+import androidx.savedstate.SavedStateRegistry
+import androidx.savedstate.SavedStateRegistryController
+import androidx.savedstate.SavedStateRegistryOwner
+import com.android.compose.animation.ViewTreeSavedStateRegistryOwner
+import com.android.systemui.lifecycle.ViewLifecycleOwner
+
+internal object ComposeInitializerImpl : ComposeInitializer {
+ override fun onAttachedToWindow(root: View) {
+ if (ViewTreeLifecycleOwner.get(root) != null) {
+ error("root $root already has a LifecycleOwner")
+ }
+
+ val parent = root.parent
+ if (parent is View && parent.id != android.R.id.content) {
+ error(
+ "ComposeInitializer.onAttachedToWindow(View) must be called on the content child." +
+ "Outside of activities and dialogs, this is usually the top-most View of a " +
+ "window."
+ )
+ }
+
+ // The lifecycle owner, which is STARTED when [root] is visible and RESUMED when [root] is
+ // both visible and focused.
+ val lifecycleOwner = ViewLifecycleOwner(root)
+
+ // We create a trivial implementation of [SavedStateRegistryOwner] that does not do any save
+ // or restore because SystemUI process is always running and top-level windows using this
+ // initializer are created once, when the process is started.
+ val savedStateRegistryOwner =
+ object : SavedStateRegistryOwner {
+ private val savedStateRegistry =
+ SavedStateRegistryController.create(this).apply { performRestore(null) }
+
+ override fun getLifecycle(): Lifecycle = lifecycleOwner.lifecycle
+
+ override fun getSavedStateRegistry(): SavedStateRegistry {
+ return savedStateRegistry.savedStateRegistry
+ }
+ }
+
+ // We must call [ViewLifecycleOwner.onCreate] after creating the [SavedStateRegistryOwner]
+ // because `onCreate` might move the lifecycle state to STARTED which will make
+ // [SavedStateRegistryController.performRestore] throw.
+ lifecycleOwner.onCreate()
+
+ // Set the owners on the root. They will be reused by any ComposeView inside the root
+ // hierarchy.
+ ViewTreeLifecycleOwner.set(root, lifecycleOwner)
+ ViewTreeSavedStateRegistryOwner.set(root, savedStateRegistryOwner)
+ }
+
+ override fun onDetachedFromWindow(root: View) {
+ (ViewTreeLifecycleOwner.get(root) as ViewLifecycleOwner).onDestroy()
+ ViewTreeLifecycleOwner.set(root, null)
+ ViewTreeSavedStateRegistryOwner.set(root, null)
+ }
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/compose/modifiers/SysuiTestTag.kt b/packages/SystemUI/compose/features/src/com/android/systemui/compose/modifiers/SysuiTestTag.kt
new file mode 100644
index 0000000..9eb78e1
--- /dev/null
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/compose/modifiers/SysuiTestTag.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.compose.modifiers
+
+import androidx.compose.ui.ExperimentalComposeUiApi
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.semantics.semantics
+import androidx.compose.ui.semantics.testTagsAsResourceId
+
+/**
+ * Set a test tag on this node so that it is associated with [resId]. This node will then be
+ * accessible by integration tests using `sysuiResSelector(resId)`.
+ */
+@OptIn(ExperimentalComposeUiApi::class)
+fun Modifier.sysuiResTag(resId: String): Modifier {
+ return this.semantics { testTagsAsResourceId = true }.testTag("com.android.systemui:id/$resId")
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreen.kt b/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreen.kt
index 23dacf9..3eeadae 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreen.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreen.kt
@@ -51,6 +51,7 @@
import androidx.lifecycle.repeatOnLifecycle
import com.android.compose.theme.LocalAndroidColorScheme
import com.android.systemui.R
+import com.android.systemui.compose.modifiers.sysuiResTag
import com.android.systemui.people.ui.viewmodel.PeopleTileViewModel
import com.android.systemui.people.ui.viewmodel.PeopleViewModel
@@ -110,7 +111,9 @@
recentTiles: List<PeopleTileViewModel>,
onTileClicked: (PeopleTileViewModel) -> Unit,
) {
- Column {
+ Column(
+ Modifier.sysuiResTag("top_level_with_conversations"),
+ ) {
Column(
Modifier.fillMaxWidth().padding(PeopleSpacePadding),
horizontalAlignment = Alignment.CenterHorizontally,
@@ -132,7 +135,7 @@
}
LazyColumn(
- Modifier.fillMaxWidth(),
+ Modifier.fillMaxWidth().sysuiResTag("scroll_view"),
contentPadding =
PaddingValues(
top = 16.dp,
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt
index 5c5ceef..349f5c3 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt
@@ -73,6 +73,7 @@
import com.android.systemui.animation.Expandable
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.common.ui.compose.Icon
+import com.android.systemui.compose.modifiers.sysuiResTag
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsButtonViewModel
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsForegroundServicesButtonViewModel
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsSecurityButtonViewModel
@@ -180,9 +181,9 @@
security?.let { SecurityButton(it, Modifier.weight(1f)) }
foregroundServices?.let { ForegroundServicesButton(it) }
- userSwitcher?.let { IconButton(it) }
- IconButton(viewModel.settings)
- viewModel.power?.let { IconButton(it) }
+ userSwitcher?.let { IconButton(it, Modifier.sysuiResTag("multi_user_switch")) }
+ IconButton(viewModel.settings, Modifier.sysuiResTag("settings_button_container"))
+ viewModel.power?.let { IconButton(it, Modifier.sysuiResTag("pm_lite")) }
}
}
}
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/customization/data/content/CustomizationProviderClient.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/customization/data/content/CustomizationProviderClient.kt
index 5bb3707..cd9fb88 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/customization/data/content/CustomizationProviderClient.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/customization/data/content/CustomizationProviderClient.kt
@@ -20,12 +20,15 @@
import android.annotation.SuppressLint
import android.content.ContentValues
import android.content.Context
+import android.content.Intent
import android.database.ContentObserver
import android.graphics.Color
import android.graphics.drawable.Drawable
import android.net.Uri
+import android.util.Log
import androidx.annotation.DrawableRes
import com.android.systemui.shared.customization.data.content.CustomizationProviderContract as Contract
+import java.net.URISyntaxException
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
@@ -169,6 +172,8 @@
* If `null`, the button should not be shown.
*/
val enablementActionComponentName: String? = null,
+ /** Optional [Intent] to use to start an activity to configure this affordance. */
+ val configureIntent: Intent? = null,
)
/** Models a selection of a quick affordance on a slot. */
@@ -337,6 +342,11 @@
Contract.LockScreenQuickAffordances.AffordanceTable.Columns
.ENABLEMENT_COMPONENT_NAME
)
+ val configureIntentColumnIndex =
+ cursor.getColumnIndex(
+ Contract.LockScreenQuickAffordances.AffordanceTable.Columns
+ .CONFIGURE_INTENT
+ )
if (
idColumnIndex == -1 ||
nameColumnIndex == -1 ||
@@ -344,15 +354,17 @@
isEnabledColumnIndex == -1 ||
enablementInstructionsColumnIndex == -1 ||
enablementActionTextColumnIndex == -1 ||
- enablementComponentNameColumnIndex == -1
+ enablementComponentNameColumnIndex == -1 ||
+ configureIntentColumnIndex == -1
) {
return@buildList
}
while (cursor.moveToNext()) {
+ val affordanceId = cursor.getString(idColumnIndex)
add(
CustomizationProviderClient.Affordance(
- id = cursor.getString(idColumnIndex),
+ id = affordanceId,
name = cursor.getString(nameColumnIndex),
iconResourceId = cursor.getInt(iconColumnIndex),
isEnabled = cursor.getInt(isEnabledColumnIndex) == 1,
@@ -367,6 +379,10 @@
cursor.getString(enablementActionTextColumnIndex),
enablementActionComponentName =
cursor.getString(enablementComponentNameColumnIndex),
+ configureIntent =
+ cursor
+ .getString(configureIntentColumnIndex)
+ ?.toIntent(affordanceId = affordanceId),
)
)
}
@@ -504,7 +520,19 @@
.onStart { emit(Unit) }
}
+ private fun String.toIntent(
+ affordanceId: String,
+ ): Intent? {
+ return try {
+ Intent.parseUri(this, 0)
+ } catch (e: URISyntaxException) {
+ Log.w(TAG, "Cannot parse Uri into Intent for affordance with ID \"$affordanceId\"!")
+ null
+ }
+ }
+
companion object {
+ private const val TAG = "CustomizationProviderClient"
private const val SYSTEM_UI_PACKAGE_NAME = "com.android.systemui"
}
}
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/customization/data/content/CustomizationProviderContract.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/customization/data/content/CustomizationProviderContract.kt
index 1e2e7d2..7f1c78f 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/customization/data/content/CustomizationProviderContract.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/customization/data/content/CustomizationProviderContract.kt
@@ -113,6 +113,11 @@
* opens a destination where the user can re-enable the disabled affordance.
*/
const val ENABLEMENT_COMPONENT_NAME = "enablement_action_intent"
+ /**
+ * Byte array. Optional parcelled `Intent` to use to start an activity that can be
+ * used to configure the affordance.
+ */
+ const val CONFIGURE_INTENT = "configure_intent"
}
}
diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags
index a4ee62c..10bb00c 100644
--- a/packages/SystemUI/proguard.flags
+++ b/packages/SystemUI/proguard.flags
@@ -24,12 +24,44 @@
# TODO(b/264686688): Handle these cases with more targeted annotations.
-keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
private com.android.keyguard.KeyguardUpdateMonitorCallback *;
+ private com.android.systemui.privacy.PrivacyConfig$Callback *;
private com.android.systemui.privacy.PrivacyItemController$Callback *;
private com.android.systemui.settings.UserTracker$Callback *;
private com.android.systemui.statusbar.phone.StatusBarWindowCallback *;
private com.android.systemui.util.service.Observer$Callback *;
private com.android.systemui.util.service.ObservableServiceConnection$Callback *;
}
+# Note that these rules are temporary companions to the above rules, required
+# for cases like Kotlin where fields with anonymous types use the anonymous type
+# rather than the supertype.
+-if class * extends com.android.keyguard.KeyguardUpdateMonitorCallback
+-keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
+ <1> *;
+}
+-if class * extends com.android.systemui.privacy.PrivacyConfig$Callback
+-keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
+ <1> *;
+}
+-if class * extends com.android.systemui.privacy.PrivacyItemController$Callback
+-keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
+ <1> *;
+}
+-if class * extends com.android.systemui.settings.UserTracker$Callback
+-keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
+ <1> *;
+}
+-if class * extends com.android.systemui.statusbar.phone.StatusBarWindowCallback
+-keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
+ <1> *;
+}
+-if class * extends com.android.systemui.util.service.Observer$Callback
+-keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
+ <1> *;
+}
+-if class * extends com.android.systemui.util.service.ObservableServiceConnection$Callback
+-keepclassmembers,allowaccessmodification class com.android.systemui.**, com.android.keyguard.** {
+ <1> *;
+}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
diff --git a/packages/SystemUI/res/drawable/accessibility_magnification_setting_view_bg.xml b/packages/SystemUI/res/drawable/accessibility_magnification_setting_view_bg.xml
index 4da47af..9fea32c 100644
--- a/packages/SystemUI/res/drawable/accessibility_magnification_setting_view_bg.xml
+++ b/packages/SystemUI/res/drawable/accessibility_magnification_setting_view_bg.xml
@@ -1,27 +1,22 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- Copyright (C) 2022 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
- <item>
- <shape android:shape="rectangle">
- <solid android:color="@color/accessibility_magnifier_bg" />
- <corners android:radius="24dp" />
- <stroke
- android:color="@color/accessibility_magnifier_bg_stroke"
- android:width="1dp" />
- </shape>
- </item>
-</layer-list>
\ No newline at end of file
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:shape="rectangle">
+ <corners android:radius="@dimen/magnification_setting_background_corner_radius" />
+ <solid android:color="?androidprv:attr/colorSurface" />
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/accessibility_window_magnification_button_bg.xml b/packages/SystemUI/res/drawable/accessibility_window_magnification_button_done_bg.xml
similarity index 65%
rename from packages/SystemUI/res/drawable/accessibility_window_magnification_button_bg.xml
rename to packages/SystemUI/res/drawable/accessibility_window_magnification_button_done_bg.xml
index eefe364..5c2bf3e 100644
--- a/packages/SystemUI/res/drawable/accessibility_window_magnification_button_bg.xml
+++ b/packages/SystemUI/res/drawable/accessibility_window_magnification_button_done_bg.xml
@@ -14,13 +14,13 @@
limitations under the License.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <solid android:color="@color/accessibility_window_magnifier_button_bg" />
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:shape="rectangle">
<size
- android:width="40dp"
- android:height="40dp"/>
- <corners android:radius="2dp"/>
+ android:width="@dimen/magnification_setting_button_done_width"
+ android:height="@dimen/magnification_setting_button_done_height"/>
+ <corners android:radius="@dimen/magnification_setting_button_done_corner_radius"/>
<stroke
- android:color="@color/accessibility_window_magnifier_button_bg_stroke"
+ android:color="?androidprv:attr/colorAccent"
android:width="1dp" />
</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_media_explicit_indicator.xml b/packages/SystemUI/res/drawable/ic_media_explicit_indicator.xml
new file mode 100644
index 0000000..08c5aaf
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_media_explicit_indicator.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="13dp"
+ android:height="13dp"
+ android:viewportWidth="48"
+ android:viewportHeight="48"
+ android:tint="?attr/colorControlNormal">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M18.3,34H29.65V31H21.3V25.7H29.65V22.7H21.3V17.35H29.65V14.35H18.3ZM9,42Q7.8,42 6.9,41.1Q6,40.2 6,39V9Q6,7.8 6.9,6.9Q7.8,6 9,6H39Q40.2,6 41.1,6.9Q42,7.8 42,9V39Q42,40.2 41.1,41.1Q40.2,42 39,42ZM9,39H39Q39,39 39,39Q39,39 39,39V9Q39,9 39,9Q39,9 39,9H9Q9,9 9,9Q9,9 9,9V39Q9,39 9,39Q9,39 9,39ZM9,9Q9,9 9,9Q9,9 9,9V39Q9,39 9,39Q9,39 9,39Q9,39 9,39Q9,39 9,39V9Q9,9 9,9Q9,9 9,9Z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/overlay_badge_background.xml b/packages/SystemUI/res/drawable/overlay_badge_background.xml
index 857632e..53122c1 100644
--- a/packages/SystemUI/res/drawable/overlay_badge_background.xml
+++ b/packages/SystemUI/res/drawable/overlay_badge_background.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+ ~ Copyright (C) 2022 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
@@ -14,8 +14,11 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
- android:shape="oval">
- <solid android:color="?androidprv:attr/colorSurface"/>
-</shape>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path
+ android:pathData="M0,0M48,48"/>
+</vector>
diff --git a/packages/SystemUI/res/layout/chipbar.xml b/packages/SystemUI/res/layout/chipbar.xml
index bc97e51..8cf4f4d 100644
--- a/packages/SystemUI/res/layout/chipbar.xml
+++ b/packages/SystemUI/res/layout/chipbar.xml
@@ -23,6 +23,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content">
+ <!-- Extra marginBottom to give room for the drop shadow. -->
<LinearLayout
android:id="@+id/chipbar_inner"
android:orientation="horizontal"
@@ -33,6 +34,8 @@
android:layout_marginTop="20dp"
android:layout_marginStart="@dimen/notification_side_paddings"
android:layout_marginEnd="@dimen/notification_side_paddings"
+ android:translationZ="4dp"
+ android:layout_marginBottom="8dp"
android:clipToPadding="false"
android:gravity="center_vertical"
android:alpha="0.0"
diff --git a/packages/SystemUI/res/layout/clipboard_overlay.xml b/packages/SystemUI/res/layout/clipboard_overlay.xml
index 9134f96..eec3b11 100644
--- a/packages/SystemUI/res/layout/clipboard_overlay.xml
+++ b/packages/SystemUI/res/layout/clipboard_overlay.xml
@@ -32,26 +32,26 @@
android:elevation="4dp"
android:background="@drawable/action_chip_container_background"
android:layout_marginStart="@dimen/overlay_action_container_margin_horizontal"
- app:layout_constraintBottom_toBottomOf="@+id/actions_container"
+ android:layout_marginBottom="@dimen/overlay_action_container_margin_bottom"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/actions_container"
- app:layout_constraintEnd_toEndOf="@+id/actions_container"/>
+ app:layout_constraintEnd_toEndOf="@+id/actions_container"
+ app:layout_constraintBottom_toBottomOf="parent"/>
<HorizontalScrollView
android:id="@+id/actions_container"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/overlay_action_container_margin_horizontal"
- android:paddingEnd="@dimen/overlay_action_container_padding_right"
+ android:paddingEnd="@dimen/overlay_action_container_padding_end"
android:paddingVertical="@dimen/overlay_action_container_padding_vertical"
android:elevation="4dp"
android:scrollbars="none"
- android:layout_marginBottom="4dp"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintWidth_percent="1.0"
app:layout_constraintWidth_max="wrap"
- app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/preview_border"
- app:layout_constraintEnd_toEndOf="parent">
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintBottom_toBottomOf="@id/actions_container_background">
<LinearLayout
android:id="@+id/actions"
android:layout_width="wrap_content"
@@ -69,44 +69,30 @@
android:id="@+id/preview_border"
android:layout_width="0dp"
android:layout_height="0dp"
- android:layout_marginStart="@dimen/overlay_offset_x"
- android:layout_marginBottom="12dp"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintBottom_toBottomOf="parent"
+ android:layout_marginStart="@dimen/overlay_preview_container_margin"
+ android:layout_marginTop="@dimen/overlay_border_width_neg"
+ android:layout_marginEnd="@dimen/overlay_border_width_neg"
+ android:layout_marginBottom="@dimen/overlay_preview_container_margin"
android:elevation="7dp"
- app:layout_constraintEnd_toEndOf="@id/clipboard_preview_end"
- app:layout_constraintTop_toTopOf="@id/clipboard_preview_top"
- android:background="@drawable/overlay_border"/>
- <androidx.constraintlayout.widget.Barrier
- android:id="@+id/clipboard_preview_end"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- app:barrierMargin="@dimen/overlay_border_width"
- app:barrierDirection="end"
- app:constraint_referenced_ids="clipboard_preview"/>
- <androidx.constraintlayout.widget.Barrier
- android:id="@+id/clipboard_preview_top"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- app:barrierDirection="top"
- app:barrierMargin="@dimen/overlay_border_width_neg"
- app:constraint_referenced_ids="clipboard_preview"/>
+ android:background="@drawable/overlay_border"
+ app:layout_constraintStart_toStartOf="@id/actions_container_background"
+ app:layout_constraintTop_toTopOf="@id/clipboard_preview"
+ app:layout_constraintEnd_toEndOf="@id/clipboard_preview"
+ app:layout_constraintBottom_toBottomOf="@id/actions_container_background"/>
<FrameLayout
android:id="@+id/clipboard_preview"
+ android:layout_width="@dimen/clipboard_preview_size"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/overlay_border_width"
+ android:layout_marginBottom="@dimen/overlay_border_width"
+ android:layout_gravity="center"
android:elevation="7dp"
android:background="@drawable/overlay_preview_background"
android:clipChildren="true"
android:clipToOutline="true"
android:clipToPadding="true"
- android:layout_width="@dimen/clipboard_preview_size"
- android:layout_margin="@dimen/overlay_border_width"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- app:layout_constraintHorizontal_bias="0"
- app:layout_constraintBottom_toBottomOf="@id/preview_border"
app:layout_constraintStart_toStartOf="@id/preview_border"
- app:layout_constraintEnd_toEndOf="@id/preview_border"
- app:layout_constraintTop_toTopOf="@id/preview_border">
+ app:layout_constraintBottom_toBottomOf="@id/preview_border">
<TextView android:id="@+id/text_preview"
android:textFontWeight="500"
android:padding="8dp"
diff --git a/packages/SystemUI/res/layout/combined_qs_header.xml b/packages/SystemUI/res/layout/combined_qs_header.xml
index a565988..d689828 100644
--- a/packages/SystemUI/res/layout/combined_qs_header.xml
+++ b/packages/SystemUI/res/layout/combined_qs_header.xml
@@ -148,9 +148,4 @@
<include layout="@layout/ongoing_privacy_chip"/>
</FrameLayout>
- <Space
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:id="@+id/space"
- />
</com.android.systemui.util.NoRemeasureMotionLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/dream_overlay_status_bar_view.xml b/packages/SystemUI/res/layout/dream_overlay_status_bar_view.xml
index 9add32c..885e5e2 100644
--- a/packages/SystemUI/res/layout/dream_overlay_status_bar_view.xml
+++ b/packages/SystemUI/res/layout/dream_overlay_status_bar_view.xml
@@ -57,6 +57,7 @@
android:layout_width="@dimen/dream_overlay_status_bar_icon_size"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/dream_overlay_status_icon_margin"
+ android:layout_marginTop="@dimen/dream_overlay_status_bar_marginTop"
android:src="@drawable/ic_alarm"
android:tint="@android:color/white"
android:visibility="gone"
@@ -67,6 +68,7 @@
android:layout_width="@dimen/dream_overlay_status_bar_icon_size"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/dream_overlay_status_icon_margin"
+ android:layout_marginTop="@dimen/dream_overlay_status_bar_marginTop"
android:src="@drawable/ic_qs_dnd_on"
android:tint="@android:color/white"
android:visibility="gone"
@@ -77,6 +79,7 @@
android:layout_width="@dimen/dream_overlay_status_bar_icon_size"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/dream_overlay_status_icon_margin"
+ android:layout_marginTop="@dimen/dream_overlay_status_bar_marginTop"
android:src="@drawable/ic_signal_wifi_off"
android:visibility="gone"
android:contentDescription="@string/dream_overlay_status_bar_wifi_off" />
diff --git a/packages/SystemUI/res/layout/media_session_view.xml b/packages/SystemUI/res/layout/media_session_view.xml
index 95aefab..abc8337 100644
--- a/packages/SystemUI/res/layout/media_session_view.xml
+++ b/packages/SystemUI/res/layout/media_session_view.xml
@@ -147,6 +147,14 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
+ <!-- Explicit Indicator -->
+ <com.android.internal.widget.CachingIconView
+ android:id="@+id/media_explicit_indicator"
+ android:layout_width="@dimen/qs_media_explicit_indicator_icon_size"
+ android:layout_height="@dimen/qs_media_explicit_indicator_icon_size"
+ android:src="@drawable/ic_media_explicit_indicator"
+ />
+
<!-- Artist name -->
<TextView
android:id="@+id/header_artist"
diff --git a/packages/SystemUI/res/layout/screenshot_static.xml b/packages/SystemUI/res/layout/screenshot_static.xml
index e4e0bd4..496eb6e 100644
--- a/packages/SystemUI/res/layout/screenshot_static.xml
+++ b/packages/SystemUI/res/layout/screenshot_static.xml
@@ -27,26 +27,26 @@
android:elevation="4dp"
android:background="@drawable/action_chip_container_background"
android:layout_marginStart="@dimen/overlay_action_container_margin_horizontal"
- app:layout_constraintBottom_toBottomOf="@+id/actions_container"
+ android:layout_marginBottom="@dimen/overlay_action_container_margin_bottom"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/actions_container"
- app:layout_constraintEnd_toEndOf="@+id/actions_container"/>
+ app:layout_constraintEnd_toEndOf="@+id/actions_container"
+ app:layout_constraintBottom_toTopOf="@id/screenshot_message_container"/>
<HorizontalScrollView
android:id="@+id/actions_container"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/overlay_action_container_margin_horizontal"
- android:layout_marginBottom="4dp"
- android:paddingEnd="@dimen/overlay_action_container_padding_right"
+ android:paddingEnd="@dimen/overlay_action_container_padding_end"
android:paddingVertical="@dimen/overlay_action_container_padding_vertical"
android:elevation="4dp"
android:scrollbars="none"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintWidth_percent="1.0"
app:layout_constraintWidth_max="wrap"
- app:layout_constraintBottom_toTopOf="@id/screenshot_message_container"
app:layout_constraintStart_toEndOf="@+id/screenshot_preview_border"
- app:layout_constraintEnd_toEndOf="parent">
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintBottom_toBottomOf="@id/actions_container_background">
<LinearLayout
android:id="@+id/screenshot_actions"
android:layout_width="wrap_content"
@@ -64,35 +64,24 @@
android:id="@+id/screenshot_preview_border"
android:layout_width="0dp"
android:layout_height="0dp"
- android:layout_marginStart="@dimen/overlay_offset_x"
- android:layout_marginBottom="12dp"
+ android:layout_marginStart="@dimen/overlay_preview_container_margin"
+ android:layout_marginTop="@dimen/overlay_border_width_neg"
+ android:layout_marginEnd="@dimen/overlay_border_width_neg"
+ android:layout_marginBottom="@dimen/overlay_preview_container_margin"
android:elevation="7dp"
android:alpha="0"
android:background="@drawable/overlay_border"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintBottom_toTopOf="@id/screenshot_message_container"
- app:layout_constraintEnd_toEndOf="@id/screenshot_preview_end"
- app:layout_constraintTop_toTopOf="@id/screenshot_preview_top"/>
- <androidx.constraintlayout.widget.Barrier
- android:id="@+id/screenshot_preview_end"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- app:barrierMargin="@dimen/overlay_border_width"
- app:barrierDirection="end"
- app:constraint_referenced_ids="screenshot_preview"/>
- <androidx.constraintlayout.widget.Barrier
- android:id="@+id/screenshot_preview_top"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- app:barrierDirection="top"
- app:barrierMargin="@dimen/overlay_border_width_neg"
- app:constraint_referenced_ids="screenshot_preview"/>
+ app:layout_constraintStart_toStartOf="@id/actions_container_background"
+ app:layout_constraintTop_toTopOf="@id/screenshot_preview"
+ app:layout_constraintEnd_toEndOf="@id/screenshot_preview"
+ app:layout_constraintBottom_toBottomOf="@id/actions_container_background"/>
<ImageView
android:id="@+id/screenshot_preview"
android:visibility="invisible"
android:layout_width="@dimen/overlay_x_scale"
- android:layout_margin="@dimen/overlay_border_width"
android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/overlay_border_width"
+ android:layout_marginBottom="@dimen/overlay_border_width"
android:layout_gravity="center"
android:elevation="7dp"
android:contentDescription="@string/screenshot_edit_description"
@@ -100,20 +89,14 @@
android:background="@drawable/overlay_preview_background"
android:adjustViewBounds="true"
android:clickable="true"
- app:layout_constraintHorizontal_bias="0"
- app:layout_constraintBottom_toBottomOf="@id/screenshot_preview_border"
app:layout_constraintStart_toStartOf="@id/screenshot_preview_border"
- app:layout_constraintEnd_toEndOf="@id/screenshot_preview_border"
- app:layout_constraintTop_toTopOf="@id/screenshot_preview_border"/>
+ app:layout_constraintBottom_toBottomOf="@id/screenshot_preview_border"/>
<ImageView
android:id="@+id/screenshot_badge"
- android:layout_width="24dp"
- android:layout_height="24dp"
- android:padding="4dp"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
android:visibility="gone"
- android:background="@drawable/overlay_badge_background"
android:elevation="8dp"
- android:src="@drawable/overlay_cancel"
app:layout_constraintBottom_toBottomOf="@id/screenshot_preview_border"
app:layout_constraintEnd_toEndOf="@id/screenshot_preview_border"/>
<FrameLayout
@@ -150,7 +133,7 @@
android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/overlay_action_container_margin_horizontal"
android:layout_marginVertical="4dp"
- android:paddingHorizontal="@dimen/overlay_action_container_padding_right"
+ android:paddingHorizontal="@dimen/overlay_action_container_padding_end"
android:paddingVertical="@dimen/overlay_action_container_padding_vertical"
android:elevation="4dp"
android:background="@drawable/action_chip_container_background"
diff --git a/packages/SystemUI/res/layout/user_switcher_fullscreen.xml b/packages/SystemUI/res/layout/user_switcher_fullscreen.xml
index fa9d739..7eaed43 100644
--- a/packages/SystemUI/res/layout/user_switcher_fullscreen.xml
+++ b/packages/SystemUI/res/layout/user_switcher_fullscreen.xml
@@ -46,7 +46,7 @@
app:layout_constraintEnd_toEndOf="parent"
app:flow_horizontalBias="0.5"
app:flow_verticalAlign="center"
- app:flow_wrapMode="chain"
+ app:flow_wrapMode="chain2"
app:flow_horizontalGap="@dimen/user_switcher_fullscreen_horizontal_gap"
app:flow_verticalGap="44dp"
app:flow_horizontalStyle="packed"/>
diff --git a/packages/SystemUI/res/layout/window_magnification_settings_view.xml b/packages/SystemUI/res/layout/window_magnification_settings_view.xml
index a3c0554..714d551 100644
--- a/packages/SystemUI/res/layout/window_magnification_settings_view.xml
+++ b/packages/SystemUI/res/layout/window_magnification_settings_view.xml
@@ -16,12 +16,13 @@
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/magnifier_panel_view"
- android:layout_width="@dimen/magnification_max_size"
- android:layout_height="match_parent"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
android:background="@drawable/accessibility_magnification_setting_view_bg"
- android:orientation="vertical">
+ android:orientation="vertical"
+ android:padding="@dimen/magnification_setting_background_padding">
<LinearLayout
- android:layout_width="@dimen/magnification_max_size"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
@@ -29,27 +30,23 @@
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/accessibility_magnifier_size"
- android:textAppearance="?android:attr/textAppearanceListItem"
- android:textColor="?android:attr/textColorAlertDialogListItem"
+ android:textAppearance="@style/TextAppearance.MagnificationSetting.Title"
android:focusable="true"
- android:layout_gravity="center_vertical|left"
- android:layout_marginStart="20dp"/>
+ android:layout_gravity="center_vertical|left" />
<Button
android:id="@+id/magnifier_edit_button"
- android:background="@drawable/accessibility_magnification_setting_view_btn_bg"
+ android:background="@null"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/accessibility_magnifier_edit"
- android:textAppearance="?android:attr/textAppearanceListItem"
- android:textColor="?android:attr/textColorAlertDialogListItem"
+ android:textAppearance="@style/TextAppearance.MagnificationSetting.EditButton"
android:focusable="true"
- android:layout_gravity="right"
- android:layout_marginEnd="20dp"/>
+ android:layout_gravity="right" />
</LinearLayout>
<LinearLayout
- android:layout_width="@dimen/magnification_max_size"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageButton
@@ -58,7 +55,6 @@
android:layout_height="56dp"
android:scaleType="center"
android:layout_weight="1"
- android:layout_marginStart="12dp"
android:background="@drawable/accessibility_magnification_setting_view_btn_bg"
android:padding="@dimen/magnification_switch_button_padding"
android:src="@drawable/ic_magnification_menu_small"
@@ -95,7 +91,6 @@
android:layout_height="56dp"
android:scaleType="center"
android:layout_weight="1"
- android:layout_marginEnd="12dp"
android:background="@drawable/accessibility_magnification_setting_view_btn_bg"
android:padding="@dimen/magnification_switch_button_padding"
android:src="@drawable/ic_open_in_new_fullscreen"
@@ -107,68 +102,53 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
- android:paddingTop="8dp"
- android:paddingEnd="20dp"
- android:paddingStart="20dp"
+ android:layout_marginTop="@dimen/magnification_setting_view_margin"
+ android:layout_marginBottom="@dimen/magnification_setting_view_margin"
android:focusable="true">
- <LinearLayout
+ <TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:background="?android:attr/selectableItemBackground"
- android:ellipsize="marquee"
- android:gravity="center_vertical"
- android:minHeight="?android:attr/listPreferredItemHeightSmall"
- android:orientation="vertical">
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:singleLine="true"
- android:text="@string/accessibility_allow_diagonal_scrolling"
- android:textAppearance="?android:attr/textAppearanceListItem"
- android:textColor="?android:attr/textColorAlertDialogListItem" />
- </LinearLayout>
+ android:singleLine="true"
+ android:text="@string/accessibility_allow_diagonal_scrolling"
+ android:textAppearance="@style/TextAppearance.MagnificationSetting.Title" />
<Switch
android:id="@+id/magnifier_horizontal_lock_switch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="right|center"
- android:theme="@android:style/Theme.DeviceDefault.DayNight"/>
+ android:layout_gravity="right" />
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/accessibility_magnification_zoom"
- android:textAppearance="?android:attr/textAppearanceListItem"
- android:textColor="?android:attr/textColorAlertDialogListItem"
- android:focusable="true"
- android:layout_marginStart="20dp"
- android:paddingTop="2dp"
- android:paddingBottom="10dp"/>
+ android:textAppearance="@style/TextAppearance.MagnificationSetting.Title"
+ android:focusable="true" />
<SeekBar
android:id="@+id/magnifier_zoom_seekbar"
android:layout_height="wrap_content"
android:layout_width="match_parent"
+ android:layout_marginTop="@dimen/magnification_setting_seekbar_margin"
android:progress="0"
- android:max="6"
- android:layout_marginEnd="20dp"
- android:theme="@android:style/Theme.DeviceDefault.DayNight"/>
-
+ android:max="6" />
<Button
- android:id="@+id/magnifier_close_button"
- android:background="@drawable/accessibility_magnification_setting_view_btn_bg"
- android:layout_width="wrap_content"
+ android:id="@+id/magnifier_done_button"
+ android:background="@drawable/accessibility_window_magnification_button_done_bg"
+ android:minHeight="@dimen/magnification_setting_button_done_height"
+ android:layout_width="@dimen/magnification_setting_button_done_width"
android:layout_height="wrap_content"
- android:text="@string/accessibility_magnification_close"
- android:textAppearance="?android:attr/textAppearanceListItem"
- android:textColor="?android:attr/textColorAlertDialogListItem"
+ android:text="@string/accessibility_magnification_done"
+ android:textAppearance="@style/TextAppearance.MagnificationSetting.DoneButton"
android:focusable="true"
android:layout_gravity="center_horizontal"
- android:paddingBottom="24dp"/>
+ android:layout_marginTop="@dimen/magnification_setting_view_margin"
+ android:paddingLeft="@dimen/magnification_setting_button_done_padding_horizontal"
+ android:paddingRight="@dimen/magnification_setting_button_done_padding_horizontal"
+ android:paddingTop="@dimen/magnification_setting_button_done_padding_vertical"
+ android:paddingBottom="@dimen/magnification_setting_button_done_padding_vertical" />
</LinearLayout>
diff --git a/packages/SystemUI/res/values-sw720dp-land/dimens.xml b/packages/SystemUI/res/values-sw720dp-land/dimens.xml
index 3fc59e3..122806a 100644
--- a/packages/SystemUI/res/values-sw720dp-land/dimens.xml
+++ b/packages/SystemUI/res/values-sw720dp-land/dimens.xml
@@ -27,7 +27,7 @@
<dimen name="status_view_margin_horizontal">24dp</dimen>
- <dimen name="qs_media_session_height_expanded">251dp</dimen>
+ <dimen name="qs_media_session_height_expanded">184dp</dimen>
<dimen name="qs_content_horizontal_padding">40dp</dimen>
<dimen name="qs_horizontal_margin">40dp</dimen>
<!-- in split shade qs_tiles_page_horizontal_margin should be equal of qs_horizontal_margin/2,
@@ -36,8 +36,8 @@
<dimen name="qs_tiles_page_horizontal_margin">20dp</dimen>
<!-- Size of Smartspace media recommendations cards in the QSPanel carousel -->
- <dimen name="qs_media_rec_icon_top_margin">27dp</dimen>
- <dimen name="qs_media_rec_album_size">152dp</dimen>
+ <dimen name="qs_media_rec_icon_top_margin">16dp</dimen>
+ <dimen name="qs_media_rec_album_size">112dp</dimen>
<dimen name="qs_media_rec_album_side_margin">16dp</dimen>
<dimen name="lockscreen_shade_max_over_scroll_amount">42dp</dimen>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index ba6977a..5bb96c4 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -175,9 +175,7 @@
<color name="accessibility_magnifier_bg">#FCFCFC</color>
<color name="accessibility_magnifier_bg_stroke">#E0E0E0</color>
<color name="accessibility_magnifier_icon_color">#252525</color>
- <color name="accessibility_window_magnifier_button_bg">#0680FD</color>
<color name="accessibility_window_magnifier_icon_color">#FAFAFA</color>
- <color name="accessibility_window_magnifier_button_bg_stroke">#252525</color>
<color name="accessibility_window_magnifier_corner_view_color">#0680FD</color>
<!-- Volume dialog colors -->
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 7f45e5e..3c2453e 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -671,6 +671,16 @@
<item>17</item> <!-- WAKE_REASON_BIOMETRIC -->
</integer-array>
+ <!-- Whether to support posture listening for face auth, default is 0(DEVICE_POSTURE_UNKNOWN)
+ means systemui will try listening on all postures.
+ 0 : DEVICE_POSTURE_UNKNOWN
+ 1 : DEVICE_POSTURE_CLOSED
+ 2 : DEVICE_POSTURE_HALF_OPENED
+ 3 : DEVICE_POSTURE_OPENED
+ 4 : DEVICE_POSTURE_FLIPPED
+ -->
+ <integer name="config_face_auth_supported_posture">0</integer>
+
<!-- Whether the communal service should be enabled -->
<bool name="config_communalServiceEnabled">false</bool>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index ae7ab9e..fc67015 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -334,15 +334,22 @@
<dimen name="overlay_action_chip_spacing">8dp</dimen>
<dimen name="overlay_action_chip_text_size">14sp</dimen>
<dimen name="overlay_offset_x">16dp</dimen>
+ <!-- Used for both start and bottom margin of the preview, relative to the action container -->
+ <dimen name="overlay_preview_container_margin">8dp</dimen>
<dimen name="overlay_action_container_margin_horizontal">8dp</dimen>
+ <dimen name="overlay_action_container_margin_bottom">4dp</dimen>
<dimen name="overlay_bg_protection_height">242dp</dimen>
<dimen name="overlay_action_container_corner_radius">18dp</dimen>
<dimen name="overlay_action_container_padding_vertical">4dp</dimen>
<dimen name="overlay_action_container_padding_right">8dp</dimen>
+ <dimen name="overlay_action_container_padding_end">8dp</dimen>
<dimen name="overlay_dismiss_button_tappable_size">48dp</dimen>
<dimen name="overlay_dismiss_button_margin">8dp</dimen>
+ <!-- must be kept aligned with overlay_border_width_neg, below;
+ overlay_border_width = overlay_border_width_neg * -1 -->
<dimen name="overlay_border_width">4dp</dimen>
- <!-- need a negative margin for some of the constraints. should be overlay_border_width * -1 -->
+ <!-- some constraints use a negative margin. must be aligned with overlay_border_width, above;
+ overlay_border_width_neg = overlay_border_width * -1 -->
<dimen name="overlay_border_width_neg">-4dp</dimen>
<dimen name="clipboard_preview_size">@dimen/overlay_x_scale</dimen>
@@ -1034,8 +1041,6 @@
<dimen name="ongoing_appops_dialog_side_padding">16dp</dimen>
- <!-- Size of the RAT type for CellularTile -->
-
<!-- Size of media cards in the QSPanel carousel -->
<dimen name="qs_media_padding">16dp</dimen>
<dimen name="qs_media_album_radius">14dp</dimen>
@@ -1050,6 +1055,7 @@
<dimen name="qs_media_disabled_seekbar_height">1dp</dimen>
<dimen name="qs_media_enabled_seekbar_height">2dp</dimen>
<dimen name="qs_media_app_icon_size">24dp</dimen>
+ <dimen name="qs_media_explicit_indicator_icon_size">13dp</dimen>
<dimen name="qs_media_session_enabled_seekbar_vertical_padding">15dp</dimen>
<dimen name="qs_media_session_disabled_seekbar_vertical_padding">16dp</dimen>
@@ -1104,13 +1110,24 @@
<!-- The extra padding to show the whole outer border -->
<dimen name="magnifier_drag_handle_padding">3dp</dimen>
<dimen name="magnification_max_frame_size">300dp</dimen>
+ <!-- Magnification settings panel -->
+ <dimen name="magnification_setting_view_margin">24dp</dimen>
+ <dimen name="magnification_setting_text_size">18sp</dimen>
+ <dimen name="magnification_setting_background_padding">24dp</dimen>
+ <dimen name="magnification_setting_background_corner_radius">28dp</dimen>
+ <dimen name="magnification_setting_seekbar_margin">16dp</dimen>
+ <dimen name="magnification_setting_button_line_height">20sp</dimen>
+ <dimen name="magnification_setting_button_done_width">312dp</dimen>
+ <dimen name="magnification_setting_button_done_height">48dp</dimen>
+ <dimen name="magnification_setting_button_done_corner_radius">100dp</dimen>
+ <dimen name="magnification_setting_button_done_padding_vertical">10dp</dimen>
+ <dimen name="magnification_setting_button_done_padding_horizontal">24dp</dimen>
<!-- How far from the right edge of the screen you need to drag the window before the button
repositions to the other side. -->
<dimen name="magnification_button_reposition_threshold_from_edge">32dp</dimen>
<dimen name="magnification_drag_size">15dp</dimen>
- <dimen name="magnification_max_size">360dp</dimen>
<dimen name="magnifier_panel_size">265dp</dimen>
<!-- Home Controls -->
@@ -1296,6 +1313,9 @@
<!-- LOCKSCREEN -> DREAMING transition: Amount to shift lockscreen content on entering -->
<dimen name="lockscreen_to_dreaming_transition_lockscreen_translation_y">-40dp</dimen>
+ <!-- GONE -> DREAMING transition: Amount to shift lockscreen content on entering -->
+ <dimen name="gone_to_dreaming_transition_lockscreen_translation_y">-40dp</dimen>
+
<!-- LOCKSCREEN -> OCCLUDED transition: Amount to shift lockscreen content on entering -->
<dimen name="lockscreen_to_occluded_transition_lockscreen_translation_y">-40dp</dimen>
@@ -1646,6 +1666,8 @@
<dimen name="dream_overlay_status_bar_ambient_text_shadow_dx">0.5dp</dimen>
<dimen name="dream_overlay_status_bar_ambient_text_shadow_dy">0.5dp</dimen>
<dimen name="dream_overlay_status_bar_ambient_text_shadow_radius">2dp</dimen>
+ <dimen name="dream_overlay_icon_inset_dimen">0dp</dimen>
+ <dimen name="dream_overlay_status_bar_marginTop">22dp</dimen>
<!-- Default device corner radius, used for assist UI -->
<dimen name="config_rounded_mask_size">0px</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 0de765f..4a89bb4 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2289,9 +2289,9 @@
<string name="accessibility_magnification_small">Small</string>
<!-- Click action label for magnification panel large size [CHAR LIMIT=NONE]-->
<string name="accessibility_magnification_large">Large</string>
- <!-- Click action label for magnification panel Close [CHAR LIMIT=NONE]-->
- <string name="accessibility_magnification_close">Close</string>
- <!-- Click action label for edit magnification size [CHAR LIMIT=NONE]-->
+ <!-- Click action label for magnification panel Done [CHAR LIMIT=20]-->
+ <string name="accessibility_magnification_done">Done</string>
+ <!-- Click action label for edit magnification size [CHAR LIMIT=20]-->
<string name="accessibility_magnifier_edit">Edit</string>
<!-- Click action label for magnification panel settings [CHAR LIMIT=NONE]-->
<string name="accessibility_magnification_magnifier_window_settings">Magnifier window settings</string>
@@ -2463,10 +2463,10 @@
<!-- Text to ask the user to move their device closer to a different device (deviceName) in order to play media on the different device. [CHAR LIMIT=75] -->
<string name="media_move_closer_to_start_cast">Move closer to play on <xliff:g id="deviceName" example="My Tablet">%1$s</xliff:g></string>
<!-- Text to ask the user to move their device closer to a different device (deviceName) in order to transfer media from the different device and back onto the current device. [CHAR LIMIT=75] -->
- <string name="media_move_closer_to_end_cast">Move closer to <xliff:g id="deviceName" example="My Tablet">%1$s</xliff:g> to play here</string>
+ <string name="media_move_closer_to_end_cast">To play here, move closer to <xliff:g id="deviceName" example="tablet">%1$s</xliff:g></string>
<!-- Text informing the user that their media is now playing on a different device (deviceName). [CHAR LIMIT=50] -->
<string name="media_transfer_playing_different_device">Playing on <xliff:g id="deviceName" example="My Tablet">%1$s</xliff:g></string>
- <!-- Text informing the user that the media transfer has failed because something went wrong. [CHAR LIsMIT=50] -->
+ <!-- Text informing the user that the media transfer has failed because something went wrong. [CHAR LIMIT=50] -->
<string name="media_transfer_failed">Something went wrong. Try again.</string>
<!-- Text to indicate that a media transfer is currently in-progress, aka loading. [CHAR LIMIT=NONE] -->
<string name="media_transfer_loading">Loading</string>
@@ -2891,6 +2891,9 @@
<!-- Text for education page content description for unfolded animation. [CHAR_LIMIT=NONE] -->
<string name="rear_display_accessibility_unfolded_animation">Foldable device being flipped around</string>
- <!-- Title for notification of low stylus battery. [CHAR_LIMIT=NONE] -->
- <string name="stylus_battery_low">Stylus battery low</string>
+ <!-- Title for notification of low stylus battery with percentage. "percentage" is
+ the value of the battery capacity remaining [CHAR LIMIT=none]-->
+ <string name="stylus_battery_low_percentage"><xliff:g id="percentage" example="16%">%s</xliff:g> battery remaining</string>
+ <!-- Subtitle for the notification sent when a stylus battery is low. [CHAR LIMIT=none]-->
+ <string name="stylus_battery_low_subtitle">Connect your stylus to a charger</string>
</resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index aafa47f..f8f5e83 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -1334,4 +1334,29 @@
<item name="biometricsEnrollProgressHelp">@color/udfps_enroll_progress_help</item>
<item name="biometricsEnrollProgressHelpWithTalkback">@color/udfps_enroll_progress_help_with_talkback</item>
</style>
+
+ <!-- Magnification styles -->
+ <style name="TextAppearance.MagnificationSetting" />
+
+ <style name="TextAppearance.MagnificationSetting.Title">
+ <item name="android:fontFamily">google-sans</item>
+ <item name="android:textColor">?androidprv:attr/textColorPrimary</item>
+ <item name="android:textSize">@dimen/magnification_setting_text_size</item>
+ </style>
+
+ <style name="TextAppearance.MagnificationSetting.EditButton">
+ <item name="android:fontFamily">google-sans</item>
+ <item name="android:textColor">?androidprv:attr/colorAccent</item>
+ <item name="android:textSize">@dimen/magnification_setting_text_size</item>
+ <item name="android:lineHeight">@dimen/magnification_setting_button_line_height</item>
+ <item name="android:textAlignment">center</item>
+ </style>
+
+ <style name="TextAppearance.MagnificationSetting.DoneButton">
+ <item name="android:fontFamily">google-sans</item>
+ <item name="android:textColor">?androidprv:attr/textColorPrimary</item>
+ <item name="android:textSize">@dimen/magnification_setting_text_size</item>
+ <item name="android:lineHeight">@dimen/magnification_setting_button_line_height</item>
+ <item name="android:textAlignment">center</item>
+ </style>
</resources>
diff --git a/packages/SystemUI/res/xml/media_session_collapsed.xml b/packages/SystemUI/res/xml/media_session_collapsed.xml
index 1eb621e..d9c81af 100644
--- a/packages/SystemUI/res/xml/media_session_collapsed.xml
+++ b/packages/SystemUI/res/xml/media_session_collapsed.xml
@@ -66,6 +66,21 @@
app:layout_constraintTop_toBottomOf="@id/icon"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintHorizontal_bias="0" />
+
+ <Constraint
+ android:id="@+id/media_explicit_indicator"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="@dimen/qs_media_info_spacing"
+ android:layout_marginBottom="@dimen/qs_media_padding"
+ android:layout_marginTop="0dp"
+ app:layout_constraintStart_toStartOf="@id/header_title"
+ app:layout_constraintEnd_toStartOf="@id/header_artist"
+ app:layout_constraintTop_toTopOf="@id/header_artist"
+ app:layout_constraintBottom_toTopOf="@id/media_action_barrier_top"
+ app:layout_constraintHorizontal_bias="0"
+ app:layout_constraintHorizontal_chainStyle="packed" />
+
<Constraint
android:id="@+id/header_artist"
android:layout_width="wrap_content"
@@ -75,9 +90,8 @@
app:layout_constraintEnd_toStartOf="@id/action_button_guideline"
app:layout_constrainedWidth="true"
app:layout_constraintTop_toBottomOf="@id/header_title"
- app:layout_constraintStart_toStartOf="@id/header_title"
- app:layout_constraintVertical_bias="0"
- app:layout_constraintHorizontal_bias="0" />
+ app:layout_constraintStart_toEndOf="@id/media_explicit_indicator"
+ app:layout_constraintVertical_bias="0" />
<Constraint
android:id="@+id/actionPlayPause"
diff --git a/packages/SystemUI/res/xml/media_session_expanded.xml b/packages/SystemUI/res/xml/media_session_expanded.xml
index 7de0a5e..0cdc0f9 100644
--- a/packages/SystemUI/res/xml/media_session_expanded.xml
+++ b/packages/SystemUI/res/xml/media_session_expanded.xml
@@ -58,6 +58,21 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toTopOf="@id/header_artist"
app:layout_constraintHorizontal_bias="0" />
+
+ <Constraint
+ android:id="@+id/media_explicit_indicator"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="@dimen/qs_media_info_spacing"
+ android:layout_marginBottom="@dimen/qs_media_padding"
+ android:layout_marginTop="0dp"
+ app:layout_constraintStart_toStartOf="@id/header_title"
+ app:layout_constraintEnd_toStartOf="@id/header_artist"
+ app:layout_constraintTop_toTopOf="@id/header_artist"
+ app:layout_constraintBottom_toTopOf="@id/media_action_barrier_top"
+ app:layout_constraintHorizontal_bias="0"
+ app:layout_constraintHorizontal_chainStyle="packed"/>
+
<Constraint
android:id="@+id/header_artist"
android:layout_width="wrap_content"
@@ -67,10 +82,9 @@
android:layout_marginTop="0dp"
app:layout_constrainedWidth="true"
app:layout_constraintEnd_toStartOf="@id/actionPlayPause"
- app:layout_constraintStart_toStartOf="@id/header_title"
+ app:layout_constraintStart_toEndOf="@id/media_explicit_indicator"
app:layout_constraintBottom_toTopOf="@id/media_action_barrier_top"
- app:layout_constraintVertical_bias="0"
- app:layout_constraintHorizontal_bias="0" />
+ app:layout_constraintVertical_bias="0" />
<Constraint
android:id="@+id/actionPlayPause"
diff --git a/packages/SystemUI/res/xml/qs_header.xml b/packages/SystemUI/res/xml/qs_header.xml
index eca2b2a..d97031f 100644
--- a/packages/SystemUI/res/xml/qs_header.xml
+++ b/packages/SystemUI/res/xml/qs_header.xml
@@ -56,13 +56,9 @@
<Layout
android:layout_width="wrap_content"
android:layout_height="@dimen/new_qs_header_non_clickable_element_height"
- app:layout_constrainedWidth="true"
app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toStartOf="@id/space"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/carrier_group"
- app:layout_constraintHorizontal_bias="0"
- app:layout_constraintHorizontal_chainStyle="spread_inside"
/>
</Constraint>
@@ -87,39 +83,27 @@
<Constraint
android:id="@+id/statusIcons">
<Layout
- android:layout_width="wrap_content"
+ android:layout_width="0dp"
android:layout_height="@dimen/new_qs_header_non_clickable_element_height"
- app:layout_constraintStart_toEndOf="@id/space"
+ app:layout_constraintWidth_default="wrap"
+ app:layout_constraintStart_toEndOf="@id/date"
app:layout_constraintEnd_toStartOf="@id/batteryRemainingIcon"
app:layout_constraintTop_toTopOf="@id/date"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintHorizontal_bias="1"
+ app:layout_constraintBottom_toBottomOf="@id/date"
/>
</Constraint>
<Constraint
android:id="@+id/batteryRemainingIcon">
<Layout
- android:layout_width="wrap_content"
+ android:layout_width="0dp"
android:layout_height="@dimen/new_qs_header_non_clickable_element_height"
+ app:layout_constraintWidth_default="wrap"
app:layout_constraintHeight_min="@dimen/new_qs_header_non_clickable_element_height"
- app:layout_constraintStart_toEndOf="@id/statusIcons"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/date"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintHorizontal_bias="1"
- app:layout_constraintHorizontal_chainStyle="spread_inside"
+ app:layout_constraintBottom_toBottomOf="@id/date"
/>
</Constraint>
-
- <Constraint
- android:id="@id/space">
- <Layout
- android:layout_width="0dp"
- android:layout_height="0dp"
- app:layout_constraintStart_toEndOf="@id/date"
- app:layout_constraintEnd_toStartOf="@id/statusIcons"
- />
- </Constraint>
</ConstraintSet>
\ No newline at end of file
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
index a71fb56..fa484c7 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
@@ -37,7 +37,7 @@
/**
* Sent when overview is to be shown.
*/
- void onOverviewShown(boolean triggeredFromAltTab) = 7;
+ void onOverviewShown(boolean triggeredFromAltTab, boolean forward) = 7;
/**
* Sent when overview is to be hidden.
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/shadow/DoubleShadowTextView.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/shadow/DoubleShadowTextView.kt
index 25d2721..9b73cc3 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/shadow/DoubleShadowTextView.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/shadow/DoubleShadowTextView.kt
@@ -48,48 +48,28 @@
val drawableInsetSize: Int
try {
val keyShadowBlur =
- attributes.getDimensionPixelSize(R.styleable.DoubleShadowTextView_keyShadowBlur, 0)
+ attributes.getDimension(R.styleable.DoubleShadowTextView_keyShadowBlur, 0f)
val keyShadowOffsetX =
- attributes.getDimensionPixelSize(
- R.styleable.DoubleShadowTextView_keyShadowOffsetX,
- 0
- )
+ attributes.getDimension(R.styleable.DoubleShadowTextView_keyShadowOffsetX, 0f)
val keyShadowOffsetY =
- attributes.getDimensionPixelSize(
- R.styleable.DoubleShadowTextView_keyShadowOffsetY,
- 0
- )
+ attributes.getDimension(R.styleable.DoubleShadowTextView_keyShadowOffsetY, 0f)
val keyShadowAlpha =
attributes.getFloat(R.styleable.DoubleShadowTextView_keyShadowAlpha, 0f)
mKeyShadowInfo =
- ShadowInfo(
- keyShadowBlur.toFloat(),
- keyShadowOffsetX.toFloat(),
- keyShadowOffsetY.toFloat(),
- keyShadowAlpha
- )
+ ShadowInfo(keyShadowBlur, keyShadowOffsetX, keyShadowOffsetY, keyShadowAlpha)
val ambientShadowBlur =
- attributes.getDimensionPixelSize(
- R.styleable.DoubleShadowTextView_ambientShadowBlur,
- 0
- )
+ attributes.getDimension(R.styleable.DoubleShadowTextView_ambientShadowBlur, 0f)
val ambientShadowOffsetX =
- attributes.getDimensionPixelSize(
- R.styleable.DoubleShadowTextView_ambientShadowOffsetX,
- 0
- )
+ attributes.getDimension(R.styleable.DoubleShadowTextView_ambientShadowOffsetX, 0f)
val ambientShadowOffsetY =
- attributes.getDimensionPixelSize(
- R.styleable.DoubleShadowTextView_ambientShadowOffsetY,
- 0
- )
+ attributes.getDimension(R.styleable.DoubleShadowTextView_ambientShadowOffsetY, 0f)
val ambientShadowAlpha =
attributes.getFloat(R.styleable.DoubleShadowTextView_ambientShadowAlpha, 0f)
mAmbientShadowInfo =
ShadowInfo(
- ambientShadowBlur.toFloat(),
- ambientShadowOffsetX.toFloat(),
- ambientShadowOffsetY.toFloat(),
+ ambientShadowBlur,
+ ambientShadowOffsetX,
+ ambientShadowOffsetY,
ambientShadowAlpha
)
drawableSize =
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
index 42422d5..6dd359c 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
@@ -283,17 +283,6 @@
}
/**
- * @return whether screen pinning is active.
- */
- public boolean isScreenPinningActive() {
- try {
- return getService().getLockTaskModeState() == LOCK_TASK_MODE_PINNED;
- } catch (RemoteException e) {
- return false;
- }
- }
-
- /**
* @return whether screen pinning is enabled.
*/
public boolean isScreenPinningEnabled() {
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
index 8af934f..dd52cfb 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
@@ -16,6 +16,7 @@
package com.android.systemui.shared.system;
+import android.annotation.NonNull;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityTaskManager;
import android.app.TaskStackListener;
@@ -27,6 +28,8 @@
import android.util.Log;
import android.window.TaskSnapshot;
+import androidx.annotation.VisibleForTesting;
+
import com.android.internal.os.SomeArgs;
import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -43,15 +46,51 @@
private final Impl mImpl;
+ /**
+ * Proxies calls to the given handler callback synchronously for testing purposes.
+ */
+ private static class TestSyncHandler extends Handler {
+ private Handler.Callback mCb;
+
+ public TestSyncHandler() {
+ super(Looper.getMainLooper());
+ }
+
+ public void setCallback(Handler.Callback cb) {
+ mCb = cb;
+ }
+
+ @Override
+ public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
+ return mCb.handleMessage(msg);
+ }
+ }
+
private TaskStackChangeListeners() {
mImpl = new Impl(Looper.getMainLooper());
}
+ private TaskStackChangeListeners(Handler h) {
+ mImpl = new Impl(h);
+ }
+
public static TaskStackChangeListeners getInstance() {
return INSTANCE;
}
/**
+ * Returns an instance of the listeners that can be called upon synchronously for testsing
+ * purposes.
+ */
+ @VisibleForTesting
+ public static TaskStackChangeListeners getTestInstance() {
+ TestSyncHandler h = new TestSyncHandler();
+ TaskStackChangeListeners l = new TaskStackChangeListeners(h);
+ h.setCallback(l.mImpl);
+ return l;
+ }
+
+ /**
* Registers a task stack listener with the system.
* This should be called on the main thread.
*/
@@ -71,7 +110,15 @@
}
}
- private static class Impl extends TaskStackListener implements Handler.Callback {
+ /**
+ * Returns an instance of the listener to call upon from tests.
+ */
+ @VisibleForTesting
+ public TaskStackListener getListenerImpl() {
+ return mImpl;
+ }
+
+ private class Impl extends TaskStackListener implements Handler.Callback {
private static final int ON_TASK_STACK_CHANGED = 1;
private static final int ON_TASK_SNAPSHOT_CHANGED = 2;
@@ -104,10 +151,14 @@
private final Handler mHandler;
private boolean mRegistered;
- Impl(Looper looper) {
+ private Impl(Looper looper) {
mHandler = new Handler(looper, this);
}
+ private Impl(Handler handler) {
+ mHandler = handler;
+ }
+
public void addListener(TaskStackChangeListener listener) {
synchronized (mTaskStackListeners) {
mTaskStackListeners.add(listener);
diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/system/SystemUnfoldSharedModule.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/system/SystemUnfoldSharedModule.kt
index 24ae42a..fe607e1 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/unfold/system/SystemUnfoldSharedModule.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/system/SystemUnfoldSharedModule.kt
@@ -19,7 +19,7 @@
import com.android.systemui.dagger.qualifiers.UiBackground
import com.android.systemui.unfold.config.ResourceUnfoldTransitionConfig
import com.android.systemui.unfold.config.UnfoldTransitionConfig
-import com.android.systemui.unfold.dagger.UnfoldBackground
+import com.android.systemui.unfold.dagger.UnfoldSingleThreadBg
import com.android.systemui.unfold.dagger.UnfoldMain
import com.android.systemui.unfold.updates.FoldProvider
import com.android.systemui.unfold.util.CurrentActivityTypeProvider
@@ -56,6 +56,6 @@
abstract fun mainHandler(@Main handler: Handler): Handler
@Binds
- @UnfoldBackground
+ @UnfoldSingleThreadBg
abstract fun backgroundExecutor(@UiBackground executor: Executor): Executor
}
diff --git a/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt b/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt
index 5bb9367..e0cf7b6 100644
--- a/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt
+++ b/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt
@@ -50,6 +50,7 @@
import com.android.keyguard.InternalFaceAuthReasons.KEYGUARD_VISIBILITY_CHANGED
import com.android.keyguard.InternalFaceAuthReasons.NON_STRONG_BIOMETRIC_ALLOWED_CHANGED
import com.android.keyguard.InternalFaceAuthReasons.OCCLUDING_APP_REQUESTED
+import com.android.keyguard.InternalFaceAuthReasons.POSTURE_CHANGED
import com.android.keyguard.InternalFaceAuthReasons.PRIMARY_BOUNCER_SHOWN
import com.android.keyguard.InternalFaceAuthReasons.PRIMARY_BOUNCER_SHOWN_OR_WILL_BE_SHOWN
import com.android.keyguard.InternalFaceAuthReasons.RETRY_AFTER_HW_UNAVAILABLE
@@ -126,6 +127,7 @@
const val STRONG_AUTH_ALLOWED_CHANGED = "Face auth stopped because strong auth allowed changed"
const val NON_STRONG_BIOMETRIC_ALLOWED_CHANGED =
"Face auth stopped because non strong biometric allowed changed"
+ const val POSTURE_CHANGED = "Face auth started/stopped due to device posture changed."
}
/**
@@ -173,6 +175,7 @@
return PowerManager.wakeReasonToString(extraInfo)
}
},
+ @UiEvent(doc = POSTURE_CHANGED) FACE_AUTH_UPDATED_POSTURE_CHANGED(1265, POSTURE_CHANGED),
@Deprecated(
"Not a face auth trigger.",
ReplaceWith(
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt
index deead19..1a06b5f 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt
@@ -39,6 +39,7 @@
var keyguardGoingAway: Boolean = false,
var listeningForFaceAssistant: Boolean = false,
var occludingAppRequestingFaceAuth: Boolean = false,
+ val postureAllowsListening: Boolean = false,
var primaryUser: Boolean = false,
var secureCameraLaunched: Boolean = false,
var supportsDetect: Boolean = false,
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
index d4ca8e3..ea84438 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
@@ -29,6 +29,9 @@
import android.view.View.OnKeyListener;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
+import android.window.OnBackAnimationCallback;
+
+import androidx.annotation.NonNull;
import com.android.keyguard.KeyguardSecurityContainer.SecurityCallback;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
@@ -394,6 +397,14 @@
}
/**
+ * @return the {@link OnBackAnimationCallback} to animate this view during a back gesture.
+ */
+ @NonNull
+ public OnBackAnimationCallback getBackCallback() {
+ return mKeyguardSecurityContainerController.getBackCallback();
+ }
+
+ /**
* Allows the media keys to work when the keyguard is showing.
* The media keys should be of no interest to the actual keyguard view(s),
* so intercepting them here should not be of any harm.
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 5d7a6f1..e4f85db 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -32,6 +32,7 @@
import static androidx.constraintlayout.widget.ConstraintSet.TOP;
import static androidx.constraintlayout.widget.ConstraintSet.WRAP_CONTENT;
+import static com.android.systemui.animation.InterpolatorsAndroidX.DECELERATE_QUINT;
import static com.android.systemui.plugins.FalsingManager.LOW_PENALTY;
import static java.lang.Integer.max;
@@ -73,6 +74,8 @@
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
+import android.window.BackEvent;
+import android.window.OnBackAnimationCallback;
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
@@ -135,7 +138,9 @@
private static final float MIN_DRAG_SIZE = 10;
// How much to scale the default slop by, to avoid accidental drags.
private static final float SLOP_SCALE = 4f;
-
+ @VisibleForTesting
+ // How much the view scales down to during back gestures.
+ static final float MIN_BACK_SCALE = 0.9f;
@VisibleForTesting
KeyguardSecurityViewFlipper mSecurityViewFlipper;
private GlobalSettings mGlobalSettings;
@@ -240,6 +245,33 @@
}
};
+ private final OnBackAnimationCallback mBackCallback = new OnBackAnimationCallback() {
+ @Override
+ public void onBackCancelled() {
+ // TODO(b/259608500): Remove once back API auto animates progress to 0 on cancel.
+ resetScale();
+ }
+
+ @Override
+ public void onBackInvoked() { }
+
+ @Override
+ public void onBackProgressed(BackEvent event) {
+ float progress = event.getProgress();
+ // TODO(b/263819310): Update the interpolator to match spec.
+ float scale = MIN_BACK_SCALE
+ + (1 - MIN_BACK_SCALE) * (1 - DECELERATE_QUINT.getInterpolation(progress));
+ setScale(scale);
+ }
+ };
+ /**
+ * @return the {@link OnBackAnimationCallback} to animate this view during a back gesture.
+ */
+ @NonNull
+ OnBackAnimationCallback getBackCallback() {
+ return mBackCallback;
+ }
+
// Used to notify the container when something interesting happens.
public interface SecurityCallback {
/**
@@ -736,6 +768,15 @@
mViewMode.onDensityOrFontScaleChanged();
}
+ void resetScale() {
+ setScale(1);
+ }
+
+ private void setScale(float scale) {
+ setScaleX(scale);
+ setScaleY(scale);
+ }
+
/**
* Enscapsulates the differences between bouncer modes for the container.
*/
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index a72a484..57bfe54 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -40,7 +40,9 @@
import android.util.Slog;
import android.view.MotionEvent;
import android.view.View;
+import android.window.OnBackAnimationCallback;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
@@ -479,6 +481,9 @@
/** Called when the bouncer changes visibility. */
public void onBouncerVisibilityChanged(@View.Visibility int visibility) {
setBouncerVisible(visibility == View.VISIBLE);
+ if (visibility == View.INVISIBLE) {
+ mView.resetScale();
+ }
}
private void setBouncerVisible(boolean visible) {
@@ -588,6 +593,14 @@
}
/**
+ * @return the {@link OnBackAnimationCallback} to animate this view during a back gesture.
+ */
+ @NonNull
+ OnBackAnimationCallback getBackCallback() {
+ return mView.getBackCallback();
+ }
+
+ /**
* Switches to the given security view unless it's already being shown, in which case
* this is a no-op.
*
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index b0c9c1e..9d6bb08 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -63,11 +63,13 @@
import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_UPDATED_KEYGUARD_VISIBILITY_CHANGED;
import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_UPDATED_ON_FACE_AUTHENTICATED;
import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_UPDATED_ON_KEYGUARD_INIT;
+import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_UPDATED_POSTURE_CHANGED;
import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_UPDATED_PRIMARY_BOUNCER_SHOWN;
import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_UPDATED_STARTED_WAKING_UP;
import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_UPDATED_STRONG_AUTH_CHANGED;
import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_UPDATED_USER_SWITCHING;
import static com.android.systemui.DejankUtils.whitelistIpcs;
+import static com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_UNKNOWN;
import android.annotation.AnyThread;
import android.annotation.MainThread;
@@ -154,6 +156,7 @@
import com.android.systemui.shared.system.TaskStackChangeListeners;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
+import com.android.systemui.statusbar.policy.DevicePostureController;
import com.android.systemui.telephony.TelephonyListenerManager;
import com.android.systemui.util.Assert;
import com.android.systemui.util.settings.SecureSettings;
@@ -341,6 +344,7 @@
private final TrustManager mTrustManager;
private final UserManager mUserManager;
private final DevicePolicyManager mDevicePolicyManager;
+ private final DevicePostureController mPostureController;
private final BroadcastDispatcher mBroadcastDispatcher;
private final SecureSettings mSecureSettings;
private final InteractionJankMonitor mInteractionJankMonitor;
@@ -358,6 +362,9 @@
private final FaceManager mFaceManager;
private final LockPatternUtils mLockPatternUtils;
private final boolean mWakeOnFingerprintAcquiredStart;
+ @VisibleForTesting
+ @DevicePostureController.DevicePostureInt
+ protected int mConfigFaceAuthSupportedPosture;
private KeyguardBypassController mKeyguardBypassController;
private List<SubscriptionInfo> mSubscriptionInfo;
@@ -368,6 +375,7 @@
private boolean mLogoutEnabled;
private boolean mIsFaceEnrolled;
private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ private int mPostureState = DEVICE_POSTURE_UNKNOWN;
private FingerprintInteractiveToAuthProvider mFingerprintInteractiveToAuthProvider;
/**
@@ -1779,6 +1787,17 @@
};
@VisibleForTesting
+ final DevicePostureController.Callback mPostureCallback =
+ new DevicePostureController.Callback() {
+ @Override
+ public void onPostureChanged(int posture) {
+ mPostureState = posture;
+ updateFaceListeningState(BIOMETRIC_ACTION_UPDATE,
+ FACE_AUTH_UPDATED_POSTURE_CHANGED);
+ }
+ };
+
+ @VisibleForTesting
CancellationSignal mFingerprintCancelSignal;
@VisibleForTesting
CancellationSignal mFaceCancelSignal;
@@ -2044,6 +2063,7 @@
@Nullable FingerprintManager fingerprintManager,
@Nullable BiometricManager biometricManager,
FaceWakeUpTriggersConfig faceWakeUpTriggersConfig,
+ DevicePostureController devicePostureController,
Optional<FingerprintInteractiveToAuthProvider> interactiveToAuthProvider) {
mContext = context;
mSubscriptionManager = subscriptionManager;
@@ -2073,6 +2093,7 @@
mDreamManager = dreamManager;
mTelephonyManager = telephonyManager;
mDevicePolicyManager = devicePolicyManager;
+ mPostureController = devicePostureController;
mPackageManager = packageManager;
mFpm = fingerprintManager;
mFaceManager = faceManager;
@@ -2084,6 +2105,8 @@
R.array.config_face_acquire_device_entry_ignorelist))
.boxed()
.collect(Collectors.toSet());
+ mConfigFaceAuthSupportedPosture = mContext.getResources().getInteger(
+ R.integer.config_face_auth_supported_posture);
mFaceWakeUpTriggersConfig = faceWakeUpTriggersConfig;
mHandler = new Handler(mainLooper) {
@@ -2275,6 +2298,9 @@
FACE_AUTH_TRIGGERED_ENROLLMENTS_CHANGED));
}
});
+ if (mConfigFaceAuthSupportedPosture != DEVICE_POSTURE_UNKNOWN) {
+ mPostureController.addCallback(mPostureCallback);
+ }
updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE, FACE_AUTH_UPDATED_ON_KEYGUARD_INIT);
TaskStackChangeListeners.getInstance().registerTaskStackListener(mTaskStackListener);
@@ -2719,7 +2745,7 @@
user,
shouldListen,
biometricEnabledForUser,
- mPrimaryBouncerIsOrWillBeShowing,
+ mPrimaryBouncerIsOrWillBeShowing,
userCanSkipBouncer,
mCredentialAttempted,
mDeviceInteractive,
@@ -2779,6 +2805,9 @@
final boolean biometricEnabledForUser = mBiometricEnabledForUser.get(user);
final boolean shouldListenForFaceAssistant = shouldListenForFaceAssistant();
final boolean isUdfpsFingerDown = mAuthController.isUdfpsFingerDown();
+ final boolean isPostureAllowedForFaceAuth =
+ mConfigFaceAuthSupportedPosture == 0 /* DEVICE_POSTURE_UNKNOWN */ ? true
+ : (mPostureState == mConfigFaceAuthSupportedPosture);
// Only listen if this KeyguardUpdateMonitor belongs to the primary user. There is an
// instance of KeyguardUpdateMonitor for each user but KeyguardUpdateMonitor is user-aware.
@@ -2795,7 +2824,8 @@
&& faceAuthAllowedOrDetectionIsNeeded && mIsPrimaryUser
&& (!mSecureCameraLaunched || mOccludingAppRequestingFace)
&& faceAndFpNotAuthenticated
- && !mGoingToSleep;
+ && !mGoingToSleep
+ && isPostureAllowedForFaceAuth;
// Aggregate relevant fields for debug logging.
logListenerModelData(
@@ -2815,6 +2845,7 @@
mKeyguardGoingAway,
shouldListenForFaceAssistant,
mOccludingAppRequestingFace,
+ isPostureAllowedForFaceAuth,
mIsPrimaryUser,
mSecureCameraLaunched,
supportsDetect,
@@ -2900,7 +2931,7 @@
getKeyguardSessionId(),
faceAuthUiEvent.getExtraInfo()
);
-
+ mLogger.logFaceUnlockPossible(unlockPossible);
if (unlockPossible) {
mFaceCancelSignal = new CancellationSignal();
diff --git a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
index 21d3b24..5b42455 100644
--- a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
+++ b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
@@ -132,6 +132,12 @@
logBuffer.log(TAG, DEBUG, { int1 = faceRunningState }, { "faceRunningState: $int1" })
}
+ fun logFaceUnlockPossible(isFaceUnlockPossible: Boolean) {
+ logBuffer.log(TAG, DEBUG,
+ { bool1 = isFaceUnlockPossible },
+ {"isUnlockWithFacePossible: $bool1"})
+ }
+
fun logFingerprintAuthForWrongUser(authUserId: Int) {
logBuffer.log(TAG, DEBUG,
{ int1 = authUserId },
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIInitializer.java b/packages/SystemUI/src/com/android/systemui/SystemUIInitializer.java
index 0fc9ef9..632fcdc 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIInitializer.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIInitializer.java
@@ -22,8 +22,6 @@
import android.os.HandlerThread;
import android.util.Log;
-import androidx.annotation.Nullable;
-
import com.android.systemui.dagger.GlobalRootComponent;
import com.android.systemui.dagger.SysUIComponent;
import com.android.systemui.dagger.WMComponent;
@@ -55,7 +53,6 @@
mContext = context;
}
- @Nullable
protected abstract GlobalRootComponent.Builder getGlobalRootComponentBuilder();
/**
@@ -72,11 +69,6 @@
* Starts the initialization process. This stands up the Dagger graph.
*/
public void init(boolean fromTest) throws ExecutionException, InterruptedException {
- GlobalRootComponent.Builder globalBuilder = getGlobalRootComponentBuilder();
- if (globalBuilder == null) {
- return;
- }
-
mRootComponent = getGlobalRootComponentBuilder()
.context(mContext)
.instrumentationTest(fromTest)
@@ -127,7 +119,6 @@
.setBackAnimation(Optional.ofNullable(null))
.setDesktopMode(Optional.ofNullable(null));
}
-
mSysUIComponent = builder.build();
if (initializeComponents) {
mSysUIComponent.init();
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIInitializerImpl.kt b/packages/SystemUI/src/com/android/systemui/SystemUIInitializerImpl.kt
index 55c095b..8aa3040 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIInitializerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIInitializerImpl.kt
@@ -16,7 +16,6 @@
package com.android.systemui
-import android.app.Application
import android.content.Context
import com.android.systemui.dagger.DaggerReferenceGlobalRootComponent
import com.android.systemui.dagger.GlobalRootComponent
@@ -25,17 +24,7 @@
* {@link SystemUIInitializer} that stands up AOSP SystemUI.
*/
class SystemUIInitializerImpl(context: Context) : SystemUIInitializer(context) {
-
- override fun getGlobalRootComponentBuilder(): GlobalRootComponent.Builder? {
- return when (Application.getProcessName()) {
- SCREENSHOT_CROSS_PROFILE_PROCESS -> null
- else -> DaggerReferenceGlobalRootComponent.builder()
- }
- }
-
- companion object {
- private const val SYSTEMUI_PROCESS = "com.android.systemui"
- private const val SCREENSHOT_CROSS_PROFILE_PROCESS =
- "$SYSTEMUI_PROCESS:screenshot_cross_profile"
+ override fun getGlobalRootComponentBuilder(): GlobalRootComponent.Builder {
+ return DaggerReferenceGlobalRootComponent.builder()
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
index 4f03b63..9537ce0 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
@@ -89,6 +89,7 @@
protected WindowMagnificationController createInstance(Display display) {
final Context windowContext = mContext.createWindowContext(display,
TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY, /* options */ null);
+ windowContext.setTheme(com.android.systemui.R.style.Theme_SystemUI);
return new WindowMagnificationController(
windowContext,
mHandler,
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java
index 9f857a8..56602ad 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java
@@ -85,7 +85,7 @@
private ImageButton mSmallButton;
private ImageButton mMediumButton;
private ImageButton mLargeButton;
- private Button mCloseButton;
+ private Button mDoneButton;
private Button mEditButton;
private ImageButton mChangeModeButton;
private boolean mAllowDiagonalScrolling = false;
@@ -160,9 +160,9 @@
} else if (viewId == R.id.magnifier_large_button) {
return mContext.getResources().getString(
R.string.accessibility_magnification_large);
- } else if (viewId == R.id.magnifier_close_button) {
+ } else if (viewId == R.id.magnifier_done_button) {
return mContext.getResources().getString(
- R.string.accessibility_magnification_close);
+ R.string.accessibility_magnification_done);
} else if (viewId == R.id.magnifier_edit_button) {
return mContext.getResources().getString(
R.string.accessibility_resize);
@@ -247,7 +247,7 @@
setMagnifierSize(MagnificationSize.LARGE);
} else if (id == R.id.magnifier_edit_button) {
editMagnifierSizeMode(true);
- } else if (id == R.id.magnifier_close_button) {
+ } else if (id == R.id.magnifier_done_button) {
hideSettingPanel();
} else if (id == R.id.magnifier_full_button) {
hideSettingPanel();
@@ -381,7 +381,7 @@
mSmallButton = mSettingView.findViewById(R.id.magnifier_small_button);
mMediumButton = mSettingView.findViewById(R.id.magnifier_medium_button);
mLargeButton = mSettingView.findViewById(R.id.magnifier_large_button);
- mCloseButton = mSettingView.findViewById(R.id.magnifier_close_button);
+ mDoneButton = mSettingView.findViewById(R.id.magnifier_done_button);
mEditButton = mSettingView.findViewById(R.id.magnifier_edit_button);
mChangeModeButton = mSettingView.findViewById(R.id.magnifier_full_button);
@@ -408,8 +408,8 @@
mLargeButton.setAccessibilityDelegate(mButtonDelegate);
mLargeButton.setOnClickListener(mButtonClickListener);
- mCloseButton.setAccessibilityDelegate(mButtonDelegate);
- mCloseButton.setOnClickListener(mButtonClickListener);
+ mDoneButton.setAccessibilityDelegate(mButtonDelegate);
+ mDoneButton.setOnClickListener(mButtonClickListener);
mChangeModeButton.setAccessibilityDelegate(mButtonDelegate);
mChangeModeButton.setOnClickListener(mButtonClickListener);
@@ -428,7 +428,8 @@
}
void onConfigurationChanged(int configDiff) {
- if ((configDiff & ActivityInfo.CONFIG_UI_MODE) != 0) {
+ if ((configDiff & ActivityInfo.CONFIG_UI_MODE) != 0
+ || (configDiff & ActivityInfo.CONFIG_ASSETS_PATHS) != 0) {
boolean showSettingPanelAfterThemeChange = mIsVisible;
hideSettingPanel(/* resetPosition= */ false);
inflateView();
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index cfbde15..79c09fd 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -182,8 +182,8 @@
private int mActivePointerId = -1;
// The timestamp of the most recent touch log.
private long mTouchLogTime;
- // The timestamp of the most recent log of the UNCHANGED interaction.
- private long mLastUnchangedInteractionTime;
+ // The timestamp of the most recent log of a touch InteractionEvent.
+ private long mLastTouchInteractionTime;
// Sensor has a capture (good or bad) for this touch. No need to enable the UDFPS display mode
// anymore for this particular touch event. In other words, do not enable the UDFPS mode until
// the user touches the sensor area again.
@@ -239,6 +239,10 @@
@Override
public void dump(@NonNull PrintWriter pw, @NonNull String[] args) {
pw.println("mSensorProps=(" + mSensorProps + ")");
+ pw.println("Using new touch detection framework: " + mFeatureFlags.isEnabled(
+ Flags.UDFPS_NEW_TOUCH_DETECTION));
+ pw.println("Using ellipse touch detection: " + mFeatureFlags.isEnabled(
+ Flags.UDFPS_ELLIPSE_DETECTION));
}
public class UdfpsOverlayController extends IUdfpsOverlayController.Stub {
@@ -540,12 +544,12 @@
private void logBiometricTouch(InteractionEvent event, NormalizedTouchData data) {
if (event == InteractionEvent.UNCHANGED) {
- long sinceLastLog = mSystemClock.elapsedRealtime() - mLastUnchangedInteractionTime;
+ long sinceLastLog = mSystemClock.elapsedRealtime() - mLastTouchInteractionTime;
if (sinceLastLog < MIN_UNCHANGED_INTERACTION_LOG_INTERVAL) {
return;
}
- mLastUnchangedInteractionTime = mSystemClock.elapsedRealtime();
}
+ mLastTouchInteractionTime = mSystemClock.elapsedRealtime();
final int biometricTouchReportedTouchType = toBiometricTouchReportedTouchType(event);
final InstanceId sessionIdProvider = mSessionTracker.getSessionId(
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt
index 583ee3a..cee2282 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt
@@ -33,6 +33,7 @@
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor
+import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.shade.ShadeExpansionListener
@@ -40,7 +41,6 @@
import com.android.systemui.statusbar.LockscreenShadeTransitionController
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.notification.stack.StackStateAnimator
-import com.android.systemui.statusbar.phone.KeyguardBouncer
import com.android.systemui.statusbar.phone.KeyguardBouncer.PrimaryBouncerExpansionCallback
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager.KeyguardViewManagerCallback
@@ -112,10 +112,10 @@
}
/**
* Hidden amount of input (pin/pattern/password) bouncer. This is used
- * [KeyguardBouncer.EXPANSION_VISIBLE] (0f) to [KeyguardBouncer.EXPANSION_HIDDEN] (1f). Only
- * used for the non-modernBouncer.
+ * [KeyguardBouncerConstants.EXPANSION_VISIBLE] (0f) to
+ * [KeyguardBouncerConstants.EXPANSION_HIDDEN] (1f). Only used for the non-modernBouncer.
*/
- private var inputBouncerHiddenAmount = KeyguardBouncer.EXPANSION_HIDDEN
+ private var inputBouncerHiddenAmount = KeyguardBouncerConstants.EXPANSION_HIDDEN
private var inputBouncerExpansion = 0f // only used for modernBouncer
private val stateListener: StatusBarStateController.StateListener =
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/udfps/EllipseOverlapDetector.kt b/packages/SystemUI/src/com/android/systemui/biometrics/udfps/EllipseOverlapDetector.kt
index 8572242..682d38a 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/udfps/EllipseOverlapDetector.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/udfps/EllipseOverlapDetector.kt
@@ -18,6 +18,7 @@
import android.graphics.Point
import android.graphics.Rect
+import androidx.annotation.VisibleForTesting
import com.android.systemui.dagger.SysUISingleton
import kotlin.math.cos
import kotlin.math.pow
@@ -50,7 +51,8 @@
return result <= 1
}
- private fun calculateSensorPoints(sensorBounds: Rect): List<Point> {
+ @VisibleForTesting
+ fun calculateSensorPoints(sensorBounds: Rect): List<Point> {
val sensorX = sensorBounds.centerX()
val sensorY = sensorBounds.centerY()
val cornerOffset: Int = sensorBounds.width() / 4
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/udfps/NormalizedTouchData.kt b/packages/SystemUI/src/com/android/systemui/biometrics/udfps/NormalizedTouchData.kt
index aa60522..28bc2b7 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/udfps/NormalizedTouchData.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/udfps/NormalizedTouchData.kt
@@ -26,28 +26,28 @@
* Value obtained from [MotionEvent.getPointerId], or [MotionEvent.INVALID_POINTER_ID] if the ID
* is not available.
*/
- val pointerId: Int,
+ val pointerId: Int = MotionEvent.INVALID_POINTER_ID,
/** [MotionEvent.getRawX] mapped to natural orientation and native resolution. */
- val x: Float,
+ val x: Float = 0f,
/** [MotionEvent.getRawY] mapped to natural orientation and native resolution. */
- val y: Float,
+ val y: Float = 0f,
/** [MotionEvent.getTouchMinor] mapped to natural orientation and native resolution. */
- val minor: Float,
+ val minor: Float = 0f,
/** [MotionEvent.getTouchMajor] mapped to natural orientation and native resolution. */
- val major: Float,
+ val major: Float = 0f,
/** [MotionEvent.getOrientation] mapped to natural orientation. */
- val orientation: Float,
+ val orientation: Float = 0f,
/** [MotionEvent.getEventTime]. */
- val time: Long,
+ val time: Long = 0,
/** [MotionEvent.getDownTime]. */
- val gestureStart: Long,
+ val gestureStart: Long = 0,
) {
/**
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessor.kt b/packages/SystemUI/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessor.kt
index 693f64a..3a01cd5 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessor.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessor.kt
@@ -43,74 +43,72 @@
): TouchProcessorResult {
fun preprocess(): PreprocessedTouch {
- // TODO(b/253085297): Add multitouch support. pointerIndex can be > 0 for ACTION_MOVE.
- val pointerIndex = 0
- val touchData = event.normalize(pointerIndex, overlayParams)
- val isGoodOverlap =
- overlapDetector.isGoodOverlap(touchData, overlayParams.nativeSensorBounds)
- return PreprocessedTouch(touchData, previousPointerOnSensorId, isGoodOverlap)
+ val touchData = List(event.pointerCount) { event.normalize(it, overlayParams) }
+ val pointersOnSensor =
+ touchData
+ .filter { overlapDetector.isGoodOverlap(it, overlayParams.nativeSensorBounds) }
+ .map { it.pointerId }
+ return PreprocessedTouch(touchData, previousPointerOnSensorId, pointersOnSensor)
}
return when (event.actionMasked) {
- MotionEvent.ACTION_DOWN -> processActionDown(preprocess())
+ MotionEvent.ACTION_DOWN,
+ MotionEvent.ACTION_POINTER_DOWN,
MotionEvent.ACTION_MOVE -> processActionMove(preprocess())
- MotionEvent.ACTION_UP -> processActionUp(preprocess())
- MotionEvent.ACTION_CANCEL ->
- processActionCancel(event.normalize(pointerIndex = 0, overlayParams))
+ MotionEvent.ACTION_UP,
+ MotionEvent.ACTION_POINTER_UP ->
+ processActionUp(preprocess(), event.getPointerId(event.actionIndex))
+ MotionEvent.ACTION_CANCEL -> processActionCancel(NormalizedTouchData())
else ->
Failure("Unsupported MotionEvent." + MotionEvent.actionToString(event.actionMasked))
}
}
}
+/**
+ * [data] contains a list of NormalizedTouchData for pointers in the motionEvent ordered by
+ * pointerIndex
+ *
+ * [previousPointerOnSensorId] the pointerId of the previous pointer on the sensor,
+ * [MotionEvent.INVALID_POINTER_ID] if none
+ *
+ * [pointersOnSensor] contains a list of ids of pointers on the sensor
+ */
private data class PreprocessedTouch(
- val data: NormalizedTouchData,
+ val data: List<NormalizedTouchData>,
val previousPointerOnSensorId: Int,
- val isGoodOverlap: Boolean,
+ val pointersOnSensor: List<Int>,
)
-private fun processActionDown(touch: PreprocessedTouch): TouchProcessorResult {
- return if (touch.isGoodOverlap) {
- ProcessedTouch(InteractionEvent.DOWN, pointerOnSensorId = touch.data.pointerId, touch.data)
- } else {
- val event =
- if (touch.data.pointerId == touch.previousPointerOnSensorId) {
- InteractionEvent.UP
- } else {
- InteractionEvent.UNCHANGED
- }
- ProcessedTouch(event, pointerOnSensorId = INVALID_POINTER_ID, touch.data)
- }
-}
-
private fun processActionMove(touch: PreprocessedTouch): TouchProcessorResult {
val hadPointerOnSensor = touch.previousPointerOnSensorId != INVALID_POINTER_ID
- val interactionEvent =
- when {
- touch.isGoodOverlap && !hadPointerOnSensor -> InteractionEvent.DOWN
- !touch.isGoodOverlap && hadPointerOnSensor -> InteractionEvent.UP
- else -> InteractionEvent.UNCHANGED
- }
- val pointerOnSensorId =
- when (interactionEvent) {
- InteractionEvent.UNCHANGED -> touch.previousPointerOnSensorId
- InteractionEvent.DOWN -> touch.data.pointerId
- else -> INVALID_POINTER_ID
- }
- return ProcessedTouch(interactionEvent, pointerOnSensorId, touch.data)
+ val hasPointerOnSensor = touch.pointersOnSensor.isNotEmpty()
+ val pointerOnSensorId = touch.pointersOnSensor.firstOrNull() ?: INVALID_POINTER_ID
+
+ return if (!hadPointerOnSensor && hasPointerOnSensor) {
+ val data = touch.data.find { it.pointerId == pointerOnSensorId } ?: NormalizedTouchData()
+ ProcessedTouch(InteractionEvent.DOWN, data.pointerId, data)
+ } else if (hadPointerOnSensor && !hasPointerOnSensor) {
+ ProcessedTouch(InteractionEvent.UP, INVALID_POINTER_ID, NormalizedTouchData())
+ } else {
+ val data = touch.data.find { it.pointerId == pointerOnSensorId } ?: NormalizedTouchData()
+ ProcessedTouch(InteractionEvent.UNCHANGED, pointerOnSensorId, data)
+ }
}
-private fun processActionUp(touch: PreprocessedTouch): TouchProcessorResult {
- return if (touch.isGoodOverlap) {
- ProcessedTouch(InteractionEvent.UP, pointerOnSensorId = INVALID_POINTER_ID, touch.data)
+private fun processActionUp(touch: PreprocessedTouch, actionId: Int): TouchProcessorResult {
+ // Finger lifted and it was the only finger on the sensor
+ return if (touch.pointersOnSensor.size == 1 && touch.pointersOnSensor.contains(actionId)) {
+ ProcessedTouch(
+ InteractionEvent.UP,
+ pointerOnSensorId = INVALID_POINTER_ID,
+ NormalizedTouchData()
+ )
} else {
- val event =
- if (touch.previousPointerOnSensorId != INVALID_POINTER_ID) {
- InteractionEvent.UP
- } else {
- InteractionEvent.UNCHANGED
- }
- ProcessedTouch(event, pointerOnSensorId = INVALID_POINTER_ID, touch.data)
+ // Pick new pointerOnSensor that's not the finger that was lifted
+ val pointerOnSensorId = touch.pointersOnSensor.find { it != actionId } ?: INVALID_POINTER_ID
+ val data = touch.data.find { it.pointerId == pointerOnSensorId } ?: NormalizedTouchData()
+ ProcessedTouch(InteractionEvent.UNCHANGED, data.pointerId, data)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
index e8e1f2e..e9ac840 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
@@ -176,7 +176,8 @@
private @Classifier.InteractionType int mPriorInteractionType = Classifier.GENERIC;
@Inject
- public BrightLineFalsingManager(FalsingDataProvider falsingDataProvider,
+ public BrightLineFalsingManager(
+ FalsingDataProvider falsingDataProvider,
MetricsLogger metricsLogger,
@Named(BRIGHT_LINE_GESTURE_CLASSIFERS) Set<FalsingClassifier> classifiers,
SingleTapClassifier singleTapClassifier, LongTapClassifier longTapClassifier,
@@ -399,7 +400,9 @@
|| mDataProvider.isJustUnlockedWithFace()
|| mDataProvider.isDocked()
|| mAccessibilityManager.isTouchExplorationEnabled()
- || mDataProvider.isA11yAction();
+ || mDataProvider.isA11yAction()
+ || (mFeatureFlags.isEnabled(Flags.FALSING_OFF_FOR_UNFOLDED)
+ && !mDataProvider.isFolded());
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java
index 09ebeea..5f347c1 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java
@@ -16,6 +16,7 @@
package com.android.systemui.classifier;
+import android.hardware.devicestate.DeviceStateManager.FoldStateListener;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.MotionEvent.PointerCoords;
@@ -42,6 +43,7 @@
private final int mWidthPixels;
private final int mHeightPixels;
private BatteryController mBatteryController;
+ private final FoldStateListener mFoldStateListener;
private final DockManager mDockManager;
private final float mXdpi;
private final float mYdpi;
@@ -65,12 +67,14 @@
public FalsingDataProvider(
DisplayMetrics displayMetrics,
BatteryController batteryController,
+ FoldStateListener foldStateListener,
DockManager dockManager) {
mXdpi = displayMetrics.xdpi;
mYdpi = displayMetrics.ydpi;
mWidthPixels = displayMetrics.widthPixels;
mHeightPixels = displayMetrics.heightPixels;
mBatteryController = batteryController;
+ mFoldStateListener = foldStateListener;
mDockManager = dockManager;
FalsingClassifier.logInfo("xdpi, ydpi: " + getXdpi() + ", " + getYdpi());
@@ -376,6 +380,10 @@
return mBatteryController.isWirelessCharging() || mDockManager.isDocked();
}
+ public boolean isFolded() {
+ return Boolean.TRUE.equals(mFoldStateListener.getFolded());
+ }
+
/** Implement to be alerted abotu the beginning and ending of falsing tracking. */
public interface SessionListener {
/** Called when the lock screen is shown and falsing-tracking begins. */
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/view/LaunchableImageView.kt b/packages/SystemUI/src/com/android/systemui/common/ui/view/LaunchableImageView.kt
index f95a8ee..7bbfec7 100644
--- a/packages/SystemUI/src/com/android/systemui/common/ui/view/LaunchableImageView.kt
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/view/LaunchableImageView.kt
@@ -28,7 +28,6 @@
LaunchableViewDelegate(
this,
superSetVisibility = { super.setVisibility(it) },
- superSetTransitionVisibility = { super.setTransitionVisibility(it) },
)
constructor(context: Context?) : super(context)
@@ -53,8 +52,4 @@
override fun setVisibility(visibility: Int) {
delegate.setVisibility(visibility)
}
-
- override fun setTransitionVisibility(visibility: Int) {
- delegate.setTransitionVisibility(visibility)
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/view/LaunchableLinearLayout.kt b/packages/SystemUI/src/com/android/systemui/common/ui/view/LaunchableLinearLayout.kt
index c27b82a..ddde628 100644
--- a/packages/SystemUI/src/com/android/systemui/common/ui/view/LaunchableLinearLayout.kt
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/view/LaunchableLinearLayout.kt
@@ -28,7 +28,6 @@
LaunchableViewDelegate(
this,
superSetVisibility = { super.setVisibility(it) },
- superSetTransitionVisibility = { super.setTransitionVisibility(it) },
)
constructor(context: Context?) : super(context)
@@ -53,8 +52,4 @@
override fun setVisibility(visibility: Int) {
delegate.setVisibility(visibility)
}
-
- override fun setTransitionVisibility(visibility: Int) {
- delegate.setTransitionVisibility(visibility)
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/compose/BaseComposeFacade.kt b/packages/SystemUI/src/com/android/systemui/compose/BaseComposeFacade.kt
index e5ec727..c0f8549 100644
--- a/packages/SystemUI/src/com/android/systemui/compose/BaseComposeFacade.kt
+++ b/packages/SystemUI/src/com/android/systemui/compose/BaseComposeFacade.kt
@@ -17,8 +17,12 @@
package com.android.systemui.compose
+import android.content.Context
+import android.view.View
import androidx.activity.ComponentActivity
+import androidx.lifecycle.LifecycleOwner
import com.android.systemui.people.ui.viewmodel.PeopleViewModel
+import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
/**
* A facade to interact with Compose, when it is available.
@@ -35,10 +39,22 @@
*/
fun isComposeAvailable(): Boolean
+ /**
+ * Return the [ComposeInitializer] to make Compose usable in windows outside normal activities.
+ */
+ fun composeInitializer(): ComposeInitializer
+
/** Bind the content of [activity] to [viewModel]. */
fun setPeopleSpaceActivityContent(
activity: ComponentActivity,
viewModel: PeopleViewModel,
onResult: (PeopleViewModel.Result) -> Unit,
)
+
+ /** Create a [View] to represent [viewModel] on screen. */
+ fun createFooterActionsView(
+ context: Context,
+ viewModel: FooterActionsViewModel,
+ qsVisibilityLifecycleOwner: LifecycleOwner,
+ ): View
}
diff --git a/packages/SystemUI/src/com/android/systemui/compose/ComposeInitializer.kt b/packages/SystemUI/src/com/android/systemui/compose/ComposeInitializer.kt
new file mode 100644
index 0000000..90dc3a0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/compose/ComposeInitializer.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.compose
+
+import android.view.View
+
+/**
+ * An initializer to use Compose outside of an Activity, e.g. inside a window added directly using
+ * [android.view.WindowManager.addView] (like the shade or status bar) or inside a dialog.
+ *
+ * Example:
+ * ```
+ * windowManager.addView(MyWindowRootView(context), /* layoutParams */)
+ *
+ * class MyWindowRootView(context: Context) : FrameLayout(context) {
+ * override fun onAttachedToWindow() {
+ * super.onAttachedToWindow()
+ * ComposeInitializer.onAttachedToWindow(this)
+ * }
+ *
+ * override fun onDetachedFromWindow() {
+ * super.onDetachedFromWindow()
+ * ComposeInitializer.onDetachedFromWindow(this)
+ * }
+ * }
+ * ```
+ */
+interface ComposeInitializer {
+ /** Function to be called on your window root view's [View.onAttachedToWindow] function. */
+ fun onAttachedToWindow(root: View)
+
+ /** Function to be called on your window root view's [View.onDetachedFromWindow] function. */
+ fun onDetachedFromWindow(root: View)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingController.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingController.kt
index eed5531..9b2a224 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingController.kt
@@ -51,13 +51,22 @@
fun bindAndLoadSuggested(component: ComponentName, callback: LoadCallback)
/**
- * Request to bind to the given service.
+ * Request to bind to the given service. This should only be used for services using the full
+ * [ControlsProviderService] API, where SystemUI renders the devices' UI.
*
* @param component The [ComponentName] of the service to bind
*/
fun bindService(component: ComponentName)
/**
+ * Bind to a service that provides a Device Controls panel (embedded activity). This will allow
+ * the app to remain "warm", and reduce latency.
+ *
+ * @param component The [ComponentName] of the [ControlsProviderService] to bind.
+ */
+ fun bindServiceForPanel(component: ComponentName)
+
+ /**
* Send a subscribe message to retrieve status of a set of controls.
*
* @param structureInfo structure containing the controls to update
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt
index 2f0fd99..3d6d335 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt
@@ -170,6 +170,10 @@
retrieveLifecycleManager(component).bindService()
}
+ override fun bindServiceForPanel(component: ComponentName) {
+ retrieveLifecycleManager(component).bindServiceForPanel()
+ }
+
override fun changeUser(newUser: UserHandle) {
if (newUser == currentUser) return
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
index 2f49c3f..f29f6d0 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
@@ -189,6 +189,14 @@
fun getPreferredSelection(): SelectedItem
/**
+ * Bind to a service that provides a Device Controls panel (embedded activity). This will allow
+ * the app to remain "warm", and reduce latency.
+ *
+ * @param component The [ComponentName] of the [ControlsProviderService] to bind.
+ */
+ fun bindComponentForPanel(componentName: ComponentName)
+
+ /**
* Interface for structure to pass data to [ControlsFavoritingActivity].
*/
interface LoadData {
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
index 7b1c623..49771dd 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
@@ -479,6 +479,10 @@
bindingController.unsubscribe()
}
+ override fun bindComponentForPanel(componentName: ComponentName) {
+ bindingController.bindServiceForPanel(componentName)
+ }
+
override fun addFavorite(
componentName: ComponentName,
structureName: CharSequence,
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
index 5b38e5b..72c3a94 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
@@ -78,6 +78,10 @@
private const val DEBUG = true
private val BIND_FLAGS = Context.BIND_AUTO_CREATE or Context.BIND_FOREGROUND_SERVICE or
Context.BIND_NOT_PERCEPTIBLE
+ // Use BIND_NOT_PERCEPTIBLE so it will be at lower priority from SystemUI.
+ // However, don't use WAIVE_PRIORITY, as by itself, it will kill the app
+ // once the Task is finished in the device controls panel.
+ private val BIND_FLAGS_PANEL = Context.BIND_AUTO_CREATE or Context.BIND_NOT_PERCEPTIBLE
}
private val intent = Intent().apply {
@@ -87,18 +91,19 @@
})
}
- private fun bindService(bind: Boolean) {
+ private fun bindService(bind: Boolean, forPanel: Boolean = false) {
executor.execute {
requiresBound = bind
if (bind) {
- if (bindTryCount != MAX_BIND_RETRIES) {
+ if (bindTryCount != MAX_BIND_RETRIES && wrapper == null) {
if (DEBUG) {
Log.d(TAG, "Binding service $intent")
}
bindTryCount++
try {
+ val flags = if (forPanel) BIND_FLAGS_PANEL else BIND_FLAGS
val bound = context
- .bindServiceAsUser(intent, serviceConnection, BIND_FLAGS, user)
+ .bindServiceAsUser(intent, serviceConnection, flags, user)
if (!bound) {
context.unbindService(serviceConnection)
}
@@ -279,6 +284,10 @@
bindService(true)
}
+ fun bindServiceForPanel() {
+ bindService(bind = true, forPanel = true)
+ }
+
/**
* Request unbind from the service.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
index 1e3e5cd..6289788 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
@@ -232,6 +232,8 @@
ControlKey(selected.structure.componentName, it.ci.controlId)
}
controlsController.get().subscribeToFavorites(selected.structure)
+ } else {
+ controlsController.get().bindComponentForPanel(selected.componentName)
}
listingCallback = createCallback(::showControlsView)
}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarView.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarView.java
index f244cb0..96bce4c 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarView.java
@@ -19,6 +19,7 @@
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.content.Context;
+import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
@@ -26,6 +27,9 @@
import androidx.constraintlayout.widget.ConstraintLayout;
import com.android.systemui.R;
+import com.android.systemui.shared.shadow.DoubleShadowIconDrawable;
+import com.android.systemui.shared.shadow.DoubleShadowTextHelper.ShadowInfo;
+import com.android.systemui.statusbar.AlphaOptimizedImageView;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -60,8 +64,15 @@
public static final int STATUS_ICON_PRIORITY_MODE_ON = 6;
private final Map<Integer, View> mStatusIcons = new HashMap<>();
+ private Context mContext;
private ViewGroup mSystemStatusViewGroup;
private ViewGroup mExtraSystemStatusViewGroup;
+ private ShadowInfo mKeyShadowInfo;
+ private ShadowInfo mAmbientShadowInfo;
+ private int mDrawableSize;
+ private int mDrawableInsetSize;
+ private static final float KEY_SHADOW_ALPHA = 0.35f;
+ private static final float AMBIENT_SHADOW_ALPHA = 0.4f;
public DreamOverlayStatusBarView(Context context) {
this(context, null);
@@ -73,6 +84,7 @@
public DreamOverlayStatusBarView(Context context, AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
+ mContext = context;
}
public DreamOverlayStatusBarView(
@@ -80,14 +92,36 @@
super(context, attrs, defStyleAttr, defStyleRes);
}
+
@Override
protected void onFinishInflate() {
super.onFinishInflate();
+ mKeyShadowInfo = createShadowInfo(
+ R.dimen.dream_overlay_status_bar_key_text_shadow_radius,
+ R.dimen.dream_overlay_status_bar_key_text_shadow_dx,
+ R.dimen.dream_overlay_status_bar_key_text_shadow_dy,
+ KEY_SHADOW_ALPHA
+ );
+
+ mAmbientShadowInfo = createShadowInfo(
+ R.dimen.dream_overlay_status_bar_ambient_text_shadow_radius,
+ R.dimen.dream_overlay_status_bar_ambient_text_shadow_dx,
+ R.dimen.dream_overlay_status_bar_ambient_text_shadow_dy,
+ AMBIENT_SHADOW_ALPHA
+ );
+
+ mDrawableSize = mContext
+ .getResources()
+ .getDimensionPixelSize(R.dimen.dream_overlay_status_bar_icon_size);
+ mDrawableInsetSize = mContext
+ .getResources()
+ .getDimensionPixelSize(R.dimen.dream_overlay_icon_inset_dimen);
+
mStatusIcons.put(STATUS_ICON_WIFI_UNAVAILABLE,
- fetchStatusIconForResId(R.id.dream_overlay_wifi_status));
+ addDoubleShadow(fetchStatusIconForResId(R.id.dream_overlay_wifi_status)));
mStatusIcons.put(STATUS_ICON_ALARM_SET,
- fetchStatusIconForResId(R.id.dream_overlay_alarm_set));
+ addDoubleShadow(fetchStatusIconForResId(R.id.dream_overlay_alarm_set)));
mStatusIcons.put(STATUS_ICON_CAMERA_DISABLED,
fetchStatusIconForResId(R.id.dream_overlay_camera_off));
mStatusIcons.put(STATUS_ICON_MIC_DISABLED,
@@ -97,7 +131,7 @@
mStatusIcons.put(STATUS_ICON_NOTIFICATIONS,
fetchStatusIconForResId(R.id.dream_overlay_notification_indicator));
mStatusIcons.put(STATUS_ICON_PRIORITY_MODE_ON,
- fetchStatusIconForResId(R.id.dream_overlay_priority_mode));
+ addDoubleShadow(fetchStatusIconForResId(R.id.dream_overlay_priority_mode)));
mSystemStatusViewGroup = findViewById(R.id.dream_overlay_system_status);
mExtraSystemStatusViewGroup = findViewById(R.id.dream_overlay_extra_items);
@@ -137,4 +171,34 @@
}
return false;
}
+
+ private View addDoubleShadow(View icon) {
+ if (icon instanceof AlphaOptimizedImageView) {
+ AlphaOptimizedImageView i = (AlphaOptimizedImageView) icon;
+ Drawable drawableIcon = i.getDrawable();
+ i.setImageDrawable(new DoubleShadowIconDrawable(
+ mKeyShadowInfo,
+ mAmbientShadowInfo,
+ drawableIcon,
+ mDrawableSize,
+ mDrawableInsetSize
+ ));
+ }
+ return icon;
+ }
+
+ private ShadowInfo createShadowInfo(int blurId, int offsetXId, int offsetYId, float alpha) {
+ return new ShadowInfo(
+ fetchDimensionForResId(blurId),
+ fetchDimensionForResId(offsetXId),
+ fetchDimensionForResId(offsetYId),
+ alpha
+ );
+ }
+
+ private Float fetchDimensionForResId(int resId) {
+ return mContext
+ .getResources()
+ .getDimension(resId);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java
index 92cdcf9..44207f4 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java
@@ -36,10 +36,10 @@
import com.android.internal.logging.UiEvent;
import com.android.internal.logging.UiEventLogger;
+import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants;
import com.android.systemui.shade.ShadeExpansionChangeEvent;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.phone.CentralSurfaces;
-import com.android.systemui.statusbar.phone.KeyguardBouncer;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.wm.shell.animation.FlingAnimationUtils;
@@ -274,16 +274,18 @@
(float) Math.hypot(horizontalVelocity, verticalVelocity);
final float expansion = flingRevealsOverlay(verticalVelocity, velocityVector)
- ? KeyguardBouncer.EXPANSION_HIDDEN : KeyguardBouncer.EXPANSION_VISIBLE;
+ ? KeyguardBouncerConstants.EXPANSION_HIDDEN
+ : KeyguardBouncerConstants.EXPANSION_VISIBLE;
// Log the swiping up to show Bouncer event.
- if (!mBouncerInitiallyShowing && expansion == KeyguardBouncer.EXPANSION_VISIBLE) {
+ if (!mBouncerInitiallyShowing
+ && expansion == KeyguardBouncerConstants.EXPANSION_VISIBLE) {
mUiEventLogger.log(DreamEvent.DREAM_SWIPED);
}
flingToExpansion(verticalVelocity, expansion);
- if (expansion == KeyguardBouncer.EXPANSION_HIDDEN) {
+ if (expansion == KeyguardBouncerConstants.EXPANSION_HIDDEN) {
mStatusBarKeyguardViewManager.reset(false);
}
break;
@@ -302,7 +304,8 @@
float dragDownAmount = expansionFraction * expansionHeight;
setPanelExpansion(expansionFraction, dragDownAmount);
});
- if (!mBouncerInitiallyShowing && targetExpansion == KeyguardBouncer.EXPANSION_VISIBLE) {
+ if (!mBouncerInitiallyShowing
+ && targetExpansion == KeyguardBouncerConstants.EXPANSION_VISIBLE) {
animator.addListener(
new AnimatorListenerAdapter() {
@Override
@@ -335,7 +338,7 @@
final float targetHeight = viewHeight * expansion;
final float expansionHeight = targetHeight - currentHeight;
final ValueAnimator animator = createExpansionAnimator(expansion, expansionHeight);
- if (expansion == KeyguardBouncer.EXPANSION_HIDDEN) {
+ if (expansion == KeyguardBouncerConstants.EXPANSION_HIDDEN) {
// Hides the bouncer, i.e., fully expands the space above the bouncer.
mFlingAnimationUtilsClosing.apply(animator, currentHeight, targetHeight, velocity,
viewHeight);
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index e4e8d59..a5d9fee 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -75,9 +75,7 @@
unreleasedFlag(119, "notification_memory_logging_enabled", teamfood = true)
// TODO(b/254512731): Tracking Bug
- @JvmField
- val NOTIFICATION_DISMISSAL_FADE =
- unreleasedFlag(113, "notification_dismissal_fade", teamfood = true)
+ @JvmField val NOTIFICATION_DISMISSAL_FADE = releasedFlag(113, "notification_dismissal_fade")
// TODO(b/259558771): Tracking Bug
val STABILITY_INDEX_FIX = releasedFlag(114, "stability_index_fix")
@@ -114,8 +112,6 @@
// ** Flag retired **
// public static final BooleanFlag KEYGUARD_LAYOUT =
// new BooleanFlag(200, true);
- // TODO(b/254512713): Tracking Bug
- @JvmField val LOCKSCREEN_ANIMATIONS = releasedFlag(201, "lockscreen_animations")
// TODO(b/254512750): Tracking Bug
val NEW_UNLOCK_SWIPE_ANIMATION = releasedFlag(202, "new_unlock_swipe_animation")
@@ -202,13 +198,22 @@
/** A different path for unocclusion transitions back to keyguard */
// TODO(b/262859270): Tracking Bug
@JvmField
- val UNOCCLUSION_TRANSITION = unreleasedFlag(223, "unocclusion_transition", teamfood = false)
+ val UNOCCLUSION_TRANSITION = unreleasedFlag(223, "unocclusion_transition", teamfood = true)
// flag for controlling auto pin confirmation and material u shapes in bouncer
@JvmField
val AUTO_PIN_CONFIRMATION =
unreleasedFlag(224, "auto_pin_confirmation", "auto_pin_confirmation")
+ // TODO(b/262859270): Tracking Bug
+ @JvmField val FALSING_OFF_FOR_UNFOLDED = releasedFlag(225, "falsing_off_for_unfolded")
+
+ /** Enables code to show contextual loyalty cards in wallet entrypoints */
+ // TODO(b/247587924): Tracking Bug
+ @JvmField
+ val ENABLE_WALLET_CONTEXTUAL_LOYALTY_CARDS =
+ unreleasedFlag(226, "enable_wallet_contextual_loyalty_cards", teamfood = false)
+
// 300 - power menu
// TODO(b/254512600): Tracking Bug
@JvmField val POWER_MENU_LITE = releasedFlag(300, "power_menu_lite")
@@ -260,10 +265,11 @@
// TODO(b/256614751): Tracking Bug
val NEW_STATUS_BAR_MOBILE_ICONS_BACKEND =
- unreleasedFlag(608, "new_status_bar_mobile_icons_backend")
+ unreleasedFlag(608, "new_status_bar_mobile_icons_backend", teamfood = true)
// TODO(b/256613548): Tracking Bug
- val NEW_STATUS_BAR_WIFI_ICON_BACKEND = unreleasedFlag(609, "new_status_bar_wifi_icon_backend")
+ val NEW_STATUS_BAR_WIFI_ICON_BACKEND =
+ unreleasedFlag(609, "new_status_bar_wifi_icon_backend", teamfood = true)
// TODO(b/256623670): Tracking Bug
@JvmField
@@ -289,7 +295,7 @@
// 801 - region sampling
// TODO(b/254512848): Tracking Bug
- val REGION_SAMPLING = unreleasedFlag(801, "region_sampling", teamfood = true)
+ val REGION_SAMPLING = unreleasedFlag(801, "region_sampling")
// 803 - screen contents translation
// TODO(b/254513187): Tracking Bug
@@ -302,7 +308,7 @@
// 900 - media
// TODO(b/254512697): Tracking Bug
- val MEDIA_TAP_TO_TRANSFER = unreleasedFlag(900, "media_tap_to_transfer", teamfood = true)
+ val MEDIA_TAP_TO_TRANSFER = releasedFlag(900, "media_tap_to_transfer")
// TODO(b/254512502): Tracking Bug
val MEDIA_SESSION_ACTIONS = unreleasedFlag(901, "media_session_actions")
@@ -332,13 +338,17 @@
val MEDIA_TTT_RECEIVER_SUCCESS_RIPPLE =
unreleasedFlag(910, "media_ttt_receiver_success_ripple", teamfood = true)
+ // TODO(b/263512203): Tracking Bug
+ val MEDIA_EXPLICIT_INDICATOR = unreleasedFlag(911, "media_explicit_indicator", teamfood = true)
+
// 1000 - dock
val SIMULATE_DOCK_THROUGH_CHARGING = releasedFlag(1000, "simulate_dock_through_charging")
// TODO(b/254512758): Tracking Bug
@JvmField val ROUNDED_BOX_RIPPLE = releasedFlag(1002, "rounded_box_ripple")
- val SHOW_LOWLIGHT_ON_DIRECT_BOOT = unreleasedFlag(1003, "show_lowlight_on_direct_boot")
+ // TODO(b/265045965): Tracking Bug
+ val SHOW_LOWLIGHT_ON_DIRECT_BOOT = releasedFlag(1003, "show_lowlight_on_direct_boot")
// 1100 - windowing
@Keep
@@ -401,6 +411,17 @@
val WM_DESKTOP_WINDOWING_2 =
sysPropBooleanFlag(1112, "persist.wm.debug.desktop_mode_2", default = false)
+ // TODO(b/254513207): Tracking Bug to delete
+ @Keep
+ @JvmField
+ val WM_ENABLE_PARTIAL_SCREEN_SHARING_ENTERPRISE_POLICIES =
+ unreleasedFlag(
+ 1113,
+ name = "screen_record_enterprise_policies",
+ namespace = DeviceConfig.NAMESPACE_WINDOW_MANAGER,
+ teamfood = false
+ )
+
// 1200 - predictive back
@Keep
@JvmField
@@ -492,6 +513,7 @@
@JvmField val ENABLE_STYLUS_CHARGING_UI = unreleasedFlag(2301, "enable_stylus_charging_ui")
@JvmField
val ENABLE_USI_BATTERY_NOTIFICATIONS = unreleasedFlag(2302, "enable_usi_battery_notifications")
+ @JvmField val ENABLE_STYLUS_EDUCATION = unreleasedFlag(2303, "enable_stylus_education")
// 2400 - performance tools and debugging info
// TODO(b/238923086): Tracking Bug
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/CustomizationProvider.kt b/packages/SystemUI/src/com/android/systemui/keyguard/CustomizationProvider.kt
index eaf1081..482138e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/CustomizationProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/CustomizationProvider.kt
@@ -282,6 +282,7 @@
.ENABLEMENT_ACTION_TEXT,
Contract.LockScreenQuickAffordances.AffordanceTable.Columns
.ENABLEMENT_COMPONENT_NAME,
+ Contract.LockScreenQuickAffordances.AffordanceTable.Columns.CONFIGURE_INTENT,
)
)
.apply {
@@ -298,6 +299,7 @@
),
representation.actionText,
representation.actionComponentName,
+ representation.configureIntent?.toUri(0),
)
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 6b121b8..18854e5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -41,6 +41,7 @@
import android.animation.ValueAnimator;
import android.app.ActivityTaskManager;
import android.app.AlarmManager;
+import android.app.BroadcastOptions;
import android.app.PendingIntent;
import android.app.StatusBarManager;
import android.app.WindowConfiguration;
@@ -391,6 +392,12 @@
| Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
| Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
+ private static final Bundle USER_PRESENT_INTENT_OPTIONS =
+ BroadcastOptions.makeBasic()
+ .setDeferUntilActive(true)
+ .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT)
+ .toBundle();
+
/**
* {@link #setKeyguardEnabled} waits on this condition when it re-enables
* the keyguard.
@@ -1921,13 +1928,23 @@
return;
}
- // if the keyguard is already showing, don't bother. check flags in both files
- // to account for the hiding animation which results in a delay and discrepancy
- // between flags
+ // If the keyguard is already showing, see if we don't need to bother re-showing it. Check
+ // flags in both files to account for the hiding animation which results in a delay and
+ // discrepancy between flags.
if (mShowing && mKeyguardStateController.isShowing()) {
- if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing");
- resetStateLocked();
- return;
+ if (mPM.isInteractive()) {
+ // It's already showing, and we're not trying to show it while the screen is off.
+ // We can simply reset all of the views.
+ if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing");
+ resetStateLocked();
+ return;
+ } else {
+ // We are trying to show the keyguard while the screen is off - this results from
+ // race conditions involving locking while unlocking. Don't short-circuit here and
+ // ensure the keyguard is fully re-shown.
+ Log.e(TAG,
+ "doKeyguard: already showing, but re-showing since we're not interactive");
+ }
}
// In split system user mode, we never unlock system user.
@@ -2319,7 +2336,10 @@
Context.USER_SERVICE);
mUiBgExecutor.execute(() -> {
for (int profileId : um.getProfileIdsWithDisabled(currentUser.getIdentifier())) {
- mContext.sendBroadcastAsUser(USER_PRESENT_INTENT, UserHandle.of(profileId));
+ mContext.sendBroadcastAsUser(USER_PRESENT_INTENT,
+ UserHandle.of(profileId),
+ null,
+ USER_PRESENT_INTENT_OPTIONS);
}
mLockPatternUtils.userPresent(currentUserId);
});
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WakefulnessLifecycle.java b/packages/SystemUI/src/com/android/systemui/keyguard/WakefulnessLifecycle.java
index 017b65a..ffd8a02 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/WakefulnessLifecycle.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/WakefulnessLifecycle.java
@@ -33,6 +33,7 @@
import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.util.time.SystemClock;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
@@ -63,6 +64,7 @@
private final Context mContext;
private final DisplayMetrics mDisplayMetrics;
+ private final SystemClock mSystemClock;
@Nullable
private final IWallpaperManager mWallpaperManagerService;
@@ -71,6 +73,9 @@
private @PowerManager.WakeReason int mLastWakeReason = PowerManager.WAKE_REASON_UNKNOWN;
+ public static final long UNKNOWN_LAST_WAKE_TIME = -1;
+ private long mLastWakeTime = UNKNOWN_LAST_WAKE_TIME;
+
@Nullable
private Point mLastWakeOriginLocation = null;
@@ -84,10 +89,12 @@
public WakefulnessLifecycle(
Context context,
@Nullable IWallpaperManager wallpaperManagerService,
+ SystemClock systemClock,
DumpManager dumpManager) {
mContext = context;
mDisplayMetrics = context.getResources().getDisplayMetrics();
mWallpaperManagerService = wallpaperManagerService;
+ mSystemClock = systemClock;
dumpManager.registerDumpable(getClass().getSimpleName(), this);
}
@@ -104,6 +111,14 @@
}
/**
+ * Returns the most recent time (in device uptimeMillis) the display woke up.
+ * Returns {@link UNKNOWN_LAST_WAKE_TIME} if there hasn't been a wakeup yet.
+ */
+ public long getLastWakeTime() {
+ return mLastWakeTime;
+ }
+
+ /**
* Returns the most recent reason the device went to sleep up. This is one of
* PowerManager.GO_TO_SLEEP_REASON_*.
*/
@@ -117,6 +132,7 @@
}
setWakefulness(WAKEFULNESS_WAKING);
mLastWakeReason = pmWakeReason;
+ mLastWakeTime = mSystemClock.uptimeMillis();
updateLastWakeOriginLocation();
if (mWallpaperManagerService != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/BouncerView.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/BouncerView.kt
index 80c6130..faeb485 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/BouncerView.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/BouncerView.kt
@@ -17,6 +17,7 @@
package com.android.systemui.keyguard.data
import android.view.KeyEvent
+import android.window.OnBackAnimationCallback
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.plugins.ActivityStarter
import java.lang.ref.WeakReference
@@ -51,4 +52,6 @@
cancelAction: Runnable?,
)
fun willDismissWithActions(): Boolean
+ /** @return the {@link OnBackAnimationCallback} to animate Bouncer during a back gesture. */
+ fun getBackCallback(): OnBackAnimationCallback
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt
index 8efb366..ed1ff32 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt
@@ -17,6 +17,7 @@
package com.android.systemui.keyguard.data.quickaffordance
import android.content.Context
+import android.content.Intent
import android.net.Uri
import android.provider.Settings
import android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
@@ -39,6 +40,7 @@
import com.android.systemui.statusbar.policy.ZenModeController
import com.android.systemui.util.settings.SecureSettings
import com.android.systemui.util.settings.SettingsProxyExt.observerFlow
+import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
@@ -48,10 +50,10 @@
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart
-import javax.inject.Inject
@SysUISingleton
-class DoNotDisturbQuickAffordanceConfig constructor(
+class DoNotDisturbQuickAffordanceConfig
+constructor(
private val context: Context,
private val controller: ZenModeController,
private val secureSettings: SecureSettings,
@@ -59,7 +61,7 @@
@Background private val backgroundDispatcher: CoroutineDispatcher,
private val testConditionId: Uri?,
testDialog: EnableZenModeDialog?,
-): KeyguardQuickAffordanceConfig {
+) : KeyguardQuickAffordanceConfig {
@Inject
constructor(
@@ -76,20 +78,23 @@
private val conditionUri: Uri
get() =
- testConditionId ?: ZenModeConfig.toTimeCondition(
- context,
- settingsValue,
- userTracker.userId,
- true, /* shortVersion */
- ).id
+ testConditionId
+ ?: ZenModeConfig.toTimeCondition(
+ context,
+ settingsValue,
+ userTracker.userId,
+ true, /* shortVersion */
+ )
+ .id
private val dialog: EnableZenModeDialog by lazy {
- testDialog ?: EnableZenModeDialog(
- context,
- R.style.Theme_SystemUI_Dialog,
- true, /* cancelIsNeutral */
- ZenModeDialogMetricsLogger(context),
- )
+ testDialog
+ ?: EnableZenModeDialog(
+ context,
+ R.style.Theme_SystemUI_Dialog,
+ true, /* cancelIsNeutral */
+ ZenModeDialogMetricsLogger(context),
+ )
}
override val key: String = BuiltInKeyguardQuickAffordanceKeys.DO_NOT_DISTURB
@@ -98,58 +103,62 @@
override val pickerIconResourceId: Int = R.drawable.ic_do_not_disturb
- override val lockScreenState: Flow<KeyguardQuickAffordanceConfig.LockScreenState> = combine(
- conflatedCallbackFlow {
- val callback = object: ZenModeController.Callback {
- override fun onZenChanged(zen: Int) {
- dndMode = zen
- trySendWithFailureLogging(updateState(), TAG)
- }
+ override val lockScreenState: Flow<KeyguardQuickAffordanceConfig.LockScreenState> =
+ combine(
+ conflatedCallbackFlow {
+ val callback =
+ object : ZenModeController.Callback {
+ override fun onZenChanged(zen: Int) {
+ dndMode = zen
+ trySendWithFailureLogging(updateState(), TAG)
+ }
- override fun onZenAvailableChanged(available: Boolean) {
- isAvailable = available
- trySendWithFailureLogging(updateState(), TAG)
- }
- }
+ override fun onZenAvailableChanged(available: Boolean) {
+ isAvailable = available
+ trySendWithFailureLogging(updateState(), TAG)
+ }
+ }
- dndMode = controller.zen
- isAvailable = controller.isZenAvailable
- trySendWithFailureLogging(updateState(), TAG)
+ dndMode = controller.zen
+ isAvailable = controller.isZenAvailable
+ trySendWithFailureLogging(updateState(), TAG)
- controller.addCallback(callback)
+ controller.addCallback(callback)
- awaitClose { controller.removeCallback(callback) }
- },
- secureSettings
- .observerFlow(Settings.Secure.ZEN_DURATION)
- .onStart { emit(Unit) }
- .map { secureSettings.getInt(Settings.Secure.ZEN_DURATION, ZEN_MODE_OFF) }
- .flowOn(backgroundDispatcher)
- .distinctUntilChanged()
- .onEach { settingsValue = it }
- ) { callbackFlowValue, _ -> callbackFlowValue }
+ awaitClose { controller.removeCallback(callback) }
+ },
+ secureSettings
+ .observerFlow(Settings.Secure.ZEN_DURATION)
+ .onStart { emit(Unit) }
+ .map { secureSettings.getInt(Settings.Secure.ZEN_DURATION, ZEN_MODE_OFF) }
+ .flowOn(backgroundDispatcher)
+ .distinctUntilChanged()
+ .onEach { settingsValue = it }
+ ) { callbackFlowValue, _ -> callbackFlowValue }
override suspend fun getPickerScreenState(): KeyguardQuickAffordanceConfig.PickerScreenState {
return if (controller.isZenAvailable) {
- KeyguardQuickAffordanceConfig.PickerScreenState.Default
+ KeyguardQuickAffordanceConfig.PickerScreenState.Default(
+ configureIntent = Intent(Settings.ACTION_ZEN_MODE_SETTINGS)
+ )
} else {
KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice
}
}
- override fun onTriggered(expandable: Expandable?):
- KeyguardQuickAffordanceConfig.OnTriggeredResult {
+ override fun onTriggered(
+ expandable: Expandable?
+ ): KeyguardQuickAffordanceConfig.OnTriggeredResult {
return when {
- !isAvailable ->
- KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled
+ !isAvailable -> KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled
dndMode != ZEN_MODE_OFF -> {
controller.setZen(ZEN_MODE_OFF, null, TAG)
KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled
}
settingsValue == ZEN_DURATION_PROMPT ->
KeyguardQuickAffordanceConfig.OnTriggeredResult.ShowDialog(
- dialog.createDialog(),
- expandable
+ dialog.createDialog(),
+ expandable
)
settingsValue == ZEN_DURATION_FOREVER -> {
controller.setZen(ZEN_MODE_IMPORTANT_INTERRUPTIONS, null, TAG)
@@ -187,4 +196,4 @@
companion object {
const val TAG = "DoNotDisturbQuickAffordanceConfig"
}
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/FlashlightQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/FlashlightQuickAffordanceConfig.kt
index 62fe80a..3412f35 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/FlashlightQuickAffordanceConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/FlashlightQuickAffordanceConfig.kt
@@ -135,7 +135,7 @@
override suspend fun getPickerScreenState(): KeyguardQuickAffordanceConfig.PickerScreenState =
if (flashlightController.isAvailable) {
- KeyguardQuickAffordanceConfig.PickerScreenState.Default
+ KeyguardQuickAffordanceConfig.PickerScreenState.Default()
} else {
KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfig.kt
index 09e5ec0..a1e9137d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfig.kt
@@ -90,7 +90,7 @@
)
}
- return KeyguardQuickAffordanceConfig.PickerScreenState.Default
+ return KeyguardQuickAffordanceConfig.PickerScreenState.Default()
}
override fun onTriggered(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceConfig.kt
index 20588e9..e32edcb 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceConfig.kt
@@ -46,7 +46,7 @@
* Returns the [PickerScreenState] representing the affordance in the settings or selector
* experience.
*/
- suspend fun getPickerScreenState(): PickerScreenState = PickerScreenState.Default
+ suspend fun getPickerScreenState(): PickerScreenState = PickerScreenState.Default()
/**
* Notifies that the affordance was clicked by the user.
@@ -63,7 +63,10 @@
sealed class PickerScreenState {
/** The picker shows the item for selecting this affordance as it normally would. */
- object Default : PickerScreenState()
+ data class Default(
+ /** Optional [Intent] to use to start an activity to configure this affordance. */
+ val configureIntent: Intent? = null,
+ ) : PickerScreenState()
/**
* The picker does not show an item for selecting this affordance as it is not supported on
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfig.kt
index 4f7990f..ea6c107 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfig.kt
@@ -89,7 +89,7 @@
),
),
)
- else -> KeyguardQuickAffordanceConfig.PickerScreenState.Default
+ else -> KeyguardQuickAffordanceConfig.PickerScreenState.Default()
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfig.kt
index 1928f40..680c06b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfig.kt
@@ -128,7 +128,7 @@
actionComponentName = componentName,
)
}
- else -> KeyguardQuickAffordanceConfig.PickerScreenState.Default
+ else -> KeyguardQuickAffordanceConfig.PickerScreenState.Default()
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt
index dd1247c..61d0214 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt
@@ -20,6 +20,7 @@
import com.android.keyguard.ViewMediatorCallback
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN
import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
import com.android.systemui.keyguard.shared.model.KeyguardBouncerModel
import com.android.systemui.log.dagger.BouncerLog
@@ -73,7 +74,7 @@
* 1f = panel fully showing = bouncer fully hidden
* ```
*/
- private val _panelExpansionAmount = MutableStateFlow(KeyguardBouncer.EXPANSION_HIDDEN)
+ private val _panelExpansionAmount = MutableStateFlow(EXPANSION_HIDDEN)
val panelExpansionAmount = _panelExpansionAmount.asStateFlow()
private val _keyguardPosition = MutableStateFlow(0f)
val keyguardPosition = _keyguardPosition.asStateFlow()
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepository.kt
index e3f5e90..2b2b9d0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepository.kt
@@ -187,6 +187,8 @@
pickerState is KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice
}
.map { (config, pickerState) ->
+ val defaultPickerState =
+ pickerState as? KeyguardQuickAffordanceConfig.PickerScreenState.Default
val disabledPickerState =
pickerState as? KeyguardQuickAffordanceConfig.PickerScreenState.Disabled
KeyguardQuickAffordancePickerRepresentation(
@@ -198,6 +200,7 @@
instructions = disabledPickerState?.instructions,
actionText = disabledPickerState?.actionText,
actionComponentName = disabledPickerState?.actionComponentName,
+ configureIntent = defaultPickerState?.configureIntent,
)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
index a4fd087..d99af90 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
@@ -40,6 +40,7 @@
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.phone.BiometricUnlockController
import com.android.systemui.statusbar.phone.BiometricUnlockController.WakeAndUnlockMode
+import com.android.systemui.statusbar.phone.DozeParameters
import com.android.systemui.statusbar.policy.KeyguardStateController
import javax.inject.Inject
import kotlinx.coroutines.channels.awaitClose
@@ -88,6 +89,9 @@
/** Observable for whether the bouncer is showing. */
val isBouncerShowing: Flow<Boolean>
+ /** Is the always-on display available to be used? */
+ val isAodAvailable: Flow<Boolean>
+
/**
* Observable for whether we are in doze state.
*
@@ -182,6 +186,7 @@
private val keyguardStateController: KeyguardStateController,
private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
private val dozeTransitionListener: DozeTransitionListener,
+ private val dozeParameters: DozeParameters,
private val authController: AuthController,
private val dreamOverlayCallbackController: DreamOverlayCallbackController,
) : KeyguardRepository {
@@ -220,6 +225,31 @@
}
.distinctUntilChanged()
+ override val isAodAvailable: Flow<Boolean> =
+ conflatedCallbackFlow {
+ val callback =
+ object : DozeParameters.Callback {
+ override fun onAlwaysOnChange() {
+ trySendWithFailureLogging(
+ dozeParameters.getAlwaysOn(),
+ TAG,
+ "updated isAodAvailable"
+ )
+ }
+ }
+
+ dozeParameters.addCallback(callback)
+ // Adding the callback does not send an initial update.
+ trySendWithFailureLogging(
+ dozeParameters.getAlwaysOn(),
+ TAG,
+ "initial isAodAvailable"
+ )
+
+ awaitClose { dozeParameters.removeCallback(callback) }
+ }
+ .distinctUntilChanged()
+
override val isKeyguardOccluded: Flow<Boolean> =
conflatedCallbackFlow {
val callback =
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt
index d14b66a..0c4bca6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt
@@ -209,7 +209,7 @@
return
}
- if (state == TransitionState.FINISHED) {
+ if (state == TransitionState.FINISHED || state == TransitionState.CANCELED) {
updateTransitionId = null
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
index fd2d271..ce61f2f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
@@ -21,9 +21,9 @@
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
-import com.android.systemui.keyguard.shared.model.DozeStateModel.Companion.isDozeOff
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionInfo
+import com.android.systemui.keyguard.shared.model.WakefulnessModel.Companion.isWakingOrStartingToWake
import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
import kotlin.time.Duration
@@ -48,12 +48,11 @@
private fun listenForDozingToLockscreen() {
scope.launch {
- keyguardInteractor.dozeTransitionModel
+ keyguardInteractor.wakefulnessModel
.sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair)
- .collect { pair ->
- val (dozeTransitionModel, lastStartedTransition) = pair
+ .collect { (wakefulnessModel, lastStartedTransition) ->
if (
- isDozeOff(dozeTransitionModel.to) &&
+ isWakingOrStartingToWake(wakefulnessModel) &&
lastStartedTransition.to == KeyguardState.DOZING
) {
keyguardTransitionRepository.startTransition(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt
index 3b09ae7..7134ec0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt
@@ -21,7 +21,7 @@
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
-import com.android.systemui.keyguard.shared.model.BiometricUnlockModel.Companion.isWakeAndUnlock
+import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
import com.android.systemui.keyguard.shared.model.DozeStateModel
import com.android.systemui.keyguard.shared.model.DozeStateModel.Companion.isDozeOff
import com.android.systemui.keyguard.shared.model.KeyguardState
@@ -56,7 +56,7 @@
scope.launch {
// Using isDreamingWithOverlay provides an optimized path to LOCKSCREEN state, which
// otherwise would have gone through OCCLUDED first
- keyguardInteractor.isDreamingWithOverlay
+ keyguardInteractor.isAbleToDream
.sample(
combine(
keyguardInteractor.dozeTransitionModel,
@@ -65,8 +65,7 @@
),
::toTriple
)
- .collect { triple ->
- val (isDreaming, dozeTransitionModel, lastStartedTransition) = triple
+ .collect { (isDreaming, dozeTransitionModel, lastStartedTransition) ->
if (
!isDreaming &&
isDozeOff(dozeTransitionModel.to) &&
@@ -96,8 +95,7 @@
),
::toTriple
)
- .collect { triple ->
- val (isDreaming, isOccluded, lastStartedTransition) = triple
+ .collect { (isDreaming, isOccluded, lastStartedTransition) ->
if (
isOccluded &&
!isDreaming &&
@@ -123,24 +121,18 @@
private fun listenForDreamingToGone() {
scope.launch {
- keyguardInteractor.biometricUnlockState
- .sample(keyguardTransitionInteractor.finishedKeyguardState, ::Pair)
- .collect { pair ->
- val (biometricUnlockState, keyguardState) = pair
- if (
- keyguardState == KeyguardState.DREAMING &&
- isWakeAndUnlock(biometricUnlockState)
- ) {
- keyguardTransitionRepository.startTransition(
- TransitionInfo(
- name,
- KeyguardState.DREAMING,
- KeyguardState.GONE,
- getAnimator(),
- )
+ keyguardInteractor.biometricUnlockState.collect { biometricUnlockState ->
+ if (biometricUnlockState == BiometricUnlockModel.WAKE_AND_UNLOCK_FROM_DREAM) {
+ keyguardTransitionRepository.startTransition(
+ TransitionInfo(
+ name,
+ KeyguardState.DREAMING,
+ KeyguardState.GONE,
+ getAnimator(),
)
- }
+ )
}
+ }
}
}
@@ -151,8 +143,7 @@
keyguardTransitionInteractor.finishedKeyguardState,
::Pair
)
- .collect { pair ->
- val (dozeTransitionModel, keyguardState) = pair
+ .collect { (dozeTransitionModel, keyguardState) ->
if (
dozeTransitionModel.to == DozeStateModel.DOZE &&
keyguardState == KeyguardState.DREAMING
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt
index 553fafe..9203a9b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt
@@ -26,7 +26,10 @@
import com.android.systemui.keyguard.shared.model.WakefulnessState
import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
+import kotlin.time.Duration
+import kotlin.time.Duration.Companion.milliseconds
import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.launch
@SysUISingleton
@@ -40,7 +43,7 @@
) : TransitionInteractor(FromGoneTransitionInteractor::class.simpleName!!) {
override fun start() {
- listenForGoneToAod()
+ listenForGoneToAodOrDozing()
listenForGoneToDreaming()
}
@@ -56,7 +59,7 @@
name,
KeyguardState.GONE,
KeyguardState.DREAMING,
- getAnimator(),
+ getAnimator(TO_DREAMING_DURATION),
)
)
}
@@ -64,12 +67,18 @@
}
}
- private fun listenForGoneToAod() {
+ private fun listenForGoneToAodOrDozing() {
scope.launch {
keyguardInteractor.wakefulnessModel
- .sample(keyguardTransitionInteractor.finishedKeyguardState, ::Pair)
- .collect { pair ->
- val (wakefulnessState, keyguardState) = pair
+ .sample(
+ combine(
+ keyguardTransitionInteractor.finishedKeyguardState,
+ keyguardInteractor.isAodAvailable,
+ ::Pair
+ ),
+ ::toTriple
+ )
+ .collect { (wakefulnessState, keyguardState, isAodAvailable) ->
if (
keyguardState == KeyguardState.GONE &&
wakefulnessState.state == WakefulnessState.STARTING_TO_SLEEP
@@ -78,7 +87,11 @@
TransitionInfo(
name,
KeyguardState.GONE,
- KeyguardState.AOD,
+ if (isAodAvailable) {
+ KeyguardState.AOD
+ } else {
+ KeyguardState.DOZING
+ },
getAnimator(),
)
)
@@ -87,14 +100,15 @@
}
}
- private fun getAnimator(): ValueAnimator {
+ private fun getAnimator(duration: Duration = DEFAULT_DURATION): ValueAnimator {
return ValueAnimator().apply {
setInterpolator(Interpolators.LINEAR)
- setDuration(TRANSITION_DURATION_MS)
+ setDuration(duration.inWholeMilliseconds)
}
}
companion object {
- private const val TRANSITION_DURATION_MS = 500L
+ private val DEFAULT_DURATION = 500.milliseconds
+ val TO_DREAMING_DURATION = 933.milliseconds
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
index 20c6531..5674e2a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
@@ -21,11 +21,11 @@
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
-import com.android.systemui.keyguard.shared.model.DozeStateModel
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.StatusBarState.KEYGUARD
import com.android.systemui.keyguard.shared.model.TransitionInfo
import com.android.systemui.keyguard.shared.model.TransitionState
+import com.android.systemui.keyguard.shared.model.WakefulnessState
import com.android.systemui.shade.data.repository.ShadeRepository
import com.android.systemui.util.kotlin.sample
import java.util.UUID
@@ -48,13 +48,11 @@
private val keyguardTransitionRepository: KeyguardTransitionRepository,
) : TransitionInteractor(FromLockscreenTransitionInteractor::class.simpleName!!) {
- private var transitionId: UUID? = null
-
override fun start() {
listenForLockscreenToGone()
listenForLockscreenToOccluded()
listenForLockscreenToCamera()
- listenForLockscreenToAod()
+ listenForLockscreenToAodOrDozing()
listenForLockscreenToBouncer()
listenForLockscreenToDreaming()
listenForLockscreenToBouncerDragging()
@@ -104,6 +102,7 @@
/* Starts transitions when manually dragging up the bouncer from the lockscreen. */
private fun listenForLockscreenToBouncerDragging() {
+ var transitionId: UUID? = null
scope.launch {
shadeRepository.shadeModel
.sample(
@@ -114,25 +113,43 @@
),
::toTriple
)
- .collect { triple ->
- val (shadeModel, keyguardState, statusBarState) = triple
-
+ .collect { (shadeModel, keyguardState, statusBarState) ->
val id = transitionId
if (id != null) {
// An existing `id` means a transition is started, and calls to
- // `updateTransition` will control it until FINISHED
- keyguardTransitionRepository.updateTransition(
- id,
- 1f - shadeModel.expansionAmount,
- if (
- shadeModel.expansionAmount == 0f || shadeModel.expansionAmount == 1f
- ) {
- transitionId = null
+ // `updateTransition` will control it until FINISHED or CANCELED
+ var nextState =
+ if (shadeModel.expansionAmount == 0f) {
TransitionState.FINISHED
+ } else if (shadeModel.expansionAmount == 1f) {
+ TransitionState.CANCELED
} else {
TransitionState.RUNNING
}
+ keyguardTransitionRepository.updateTransition(
+ id,
+ 1f - shadeModel.expansionAmount,
+ nextState,
)
+
+ if (
+ nextState == TransitionState.CANCELED ||
+ nextState == TransitionState.FINISHED
+ ) {
+ transitionId = null
+ }
+
+ // If canceled, just put the state back
+ if (nextState == TransitionState.CANCELED) {
+ keyguardTransitionRepository.startTransition(
+ TransitionInfo(
+ ownerName = name,
+ from = KeyguardState.BOUNCER,
+ to = KeyguardState.LOCKSCREEN,
+ animator = getAnimator(0.milliseconds)
+ )
+ )
+ }
} else {
// TODO (b/251849525): Remove statusbarstate check when that state is
// integrated into KeyguardTransitionRepository
@@ -230,19 +247,31 @@
}
}
- private fun listenForLockscreenToAod() {
+ private fun listenForLockscreenToAodOrDozing() {
scope.launch {
- keyguardInteractor
- .dozeTransitionTo(DozeStateModel.DOZE_AOD)
- .sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair)
- .collect { pair ->
- val (dozeToAod, lastStartedStep) = pair
- if (lastStartedStep.to == KeyguardState.LOCKSCREEN) {
+ keyguardInteractor.wakefulnessModel
+ .sample(
+ combine(
+ keyguardTransitionInteractor.startedKeyguardTransitionStep,
+ keyguardInteractor.isAodAvailable,
+ ::Pair
+ ),
+ ::toTriple
+ )
+ .collect { (wakefulnessState, lastStartedStep, isAodAvailable) ->
+ if (
+ lastStartedStep.to == KeyguardState.LOCKSCREEN &&
+ wakefulnessState.state == WakefulnessState.STARTING_TO_SLEEP
+ ) {
keyguardTransitionRepository.startTransition(
TransitionInfo(
name,
KeyguardState.LOCKSCREEN,
- KeyguardState.AOD,
+ if (isAodAvailable) {
+ KeyguardState.AOD
+ } else {
+ KeyguardState.DOZING
+ },
getAnimator(),
)
)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt
index 8878901..2dc8fee 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt
@@ -23,12 +23,14 @@
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionInfo
+import com.android.systemui.keyguard.shared.model.WakefulnessState
import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.collect
+import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.launch
@SysUISingleton
@@ -44,6 +46,7 @@
override fun start() {
listenForOccludedToLockscreen()
listenForOccludedToDreaming()
+ listenForOccludedToAodOrDozing()
}
private fun listenForOccludedToDreaming() {
@@ -70,8 +73,7 @@
scope.launch {
keyguardInteractor.isKeyguardOccluded
.sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair)
- .collect { pair ->
- val (isOccluded, lastStartedKeyguardState) = pair
+ .collect { (isOccluded, lastStartedKeyguardState) ->
// Occlusion signals come from the framework, and should interrupt any
// existing transition
if (!isOccluded && lastStartedKeyguardState.to == KeyguardState.OCCLUDED) {
@@ -88,6 +90,39 @@
}
}
+ private fun listenForOccludedToAodOrDozing() {
+ scope.launch {
+ keyguardInteractor.wakefulnessModel
+ .sample(
+ combine(
+ keyguardTransitionInteractor.startedKeyguardTransitionStep,
+ keyguardInteractor.isAodAvailable,
+ ::Pair
+ ),
+ ::toTriple
+ )
+ .collect { (wakefulnessState, lastStartedStep, isAodAvailable) ->
+ if (
+ lastStartedStep.to == KeyguardState.OCCLUDED &&
+ wakefulnessState.state == WakefulnessState.STARTING_TO_SLEEP
+ ) {
+ keyguardTransitionRepository.startTransition(
+ TransitionInfo(
+ name,
+ KeyguardState.OCCLUDED,
+ if (isAodAvailable) {
+ KeyguardState.AOD
+ } else {
+ KeyguardState.DOZING
+ },
+ getAnimator(),
+ )
+ )
+ }
+ }
+ }
+ }
+
private fun getAnimator(duration: Duration = DEFAULT_DURATION): ValueAnimator {
return ValueAnimator().apply {
setInterpolator(Interpolators.LINEAR)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
index ac2d230..4cf56fe 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
@@ -32,12 +32,15 @@
import com.android.systemui.keyguard.shared.model.WakefulnessModel
import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.statusbar.CommandQueue.Callbacks
-import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.merge
/**
@@ -57,6 +60,8 @@
val dozeAmount: Flow<Float> = repository.linearDozeAmount
/** Whether the system is in doze mode. */
val isDozing: Flow<Boolean> = repository.isDozing
+ /** Whether Always-on Display mode is available. */
+ val isAodAvailable: Flow<Boolean> = repository.isAodAvailable
/** Doze transition information. */
val dozeTransitionModel: Flow<DozeTransitionModel> = repository.dozeTransitionModel
/**
@@ -87,15 +92,23 @@
/**
* Dozing and dreaming have overlapping events. If the doze state remains in FINISH, it means
* that doze mode is not running and DREAMING is ok to commence.
+ *
+ * Allow a brief moment to prevent rapidly oscillating between true/false signals.
*/
val isAbleToDream: Flow<Boolean> =
merge(isDreaming, isDreamingWithOverlay)
- .sample(
+ .combine(
dozeTransitionModel,
{ isDreaming, dozeTransitionModel ->
isDreaming && isDozeOff(dozeTransitionModel.to)
}
)
+ .flatMapLatest { isAbleToDream ->
+ flow {
+ delay(50)
+ emit(isAbleToDream)
+ }
+ }
.distinctUntilChanged()
/** Whether the keyguard is showing or not. */
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt
index 9cdbcda..ad6dbea 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt
@@ -22,13 +22,17 @@
import com.android.systemui.keyguard.shared.model.AnimationParams
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
+import com.android.systemui.keyguard.shared.model.KeyguardState.BOUNCER
import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING
+import com.android.systemui.keyguard.shared.model.KeyguardState.GONE
import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
import com.android.systemui.keyguard.shared.model.KeyguardState.OCCLUDED
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionState.STARTED
import com.android.systemui.keyguard.shared.model.TransitionStep
import javax.inject.Inject
+import kotlin.math.max
+import kotlin.math.min
import kotlin.time.Duration
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.filter
@@ -53,9 +57,16 @@
val dreamingToLockscreenTransition: Flow<TransitionStep> =
repository.transition(DREAMING, LOCKSCREEN)
+ /** GONE->DREAMING transition information. */
+ val goneToDreamingTransition: Flow<TransitionStep> = repository.transition(GONE, DREAMING)
+
/** LOCKSCREEN->AOD transition information. */
val lockscreenToAodTransition: Flow<TransitionStep> = repository.transition(LOCKSCREEN, AOD)
+ /** LOCKSCREEN->BOUNCER transition information. */
+ val lockscreenToBouncerTransition: Flow<TransitionStep> =
+ repository.transition(LOCKSCREEN, BOUNCER)
+
/** LOCKSCREEN->DREAMING transition information. */
val lockscreenToDreamingTransition: Flow<TransitionStep> =
repository.transition(LOCKSCREEN, DREAMING)
@@ -106,13 +117,23 @@
): Flow<Float> {
val start = (params.startTime / totalDuration).toFloat()
val chunks = (totalDuration / params.duration).toFloat()
+ var isRunning = false
return flow
- // When starting, emit a value of 0f to give animations a chance to set initial state
.map { step ->
+ val value = (step.value - start) * chunks
if (step.transitionState == STARTED) {
- 0f
+ // When starting, make sure to always emit. If a transition is started from the
+ // middle, it is possible this animation is being skipped but we need to inform
+ // the ViewModels of the last update
+ isRunning = true
+ max(0f, min(1f, value))
+ } else if (isRunning && value >= 1f) {
+ // Always send a final value of 1. Because of rounding, [value] may never be
+ // exactly 1.
+ isRunning = false
+ 1f
} else {
- (step.value - start) * chunks
+ value
}
}
.filter { value -> value >= 0f && value <= 1f }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt
index 2cf5fb9..a92540d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt
@@ -32,11 +32,11 @@
import com.android.systemui.keyguard.DismissCallbackRegistry
import com.android.systemui.keyguard.data.BouncerView
import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
+import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants
import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
import com.android.systemui.keyguard.shared.model.KeyguardBouncerModel
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.shared.system.SysUiStatsLog
-import com.android.systemui.statusbar.phone.KeyguardBouncer
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.policy.KeyguardStateController
import javax.inject.Inject
@@ -143,7 +143,7 @@
Trace.beginSection("KeyguardBouncer#show")
repository.setPrimaryScrimmed(isScrimmed)
if (isScrimmed) {
- setPanelExpansion(KeyguardBouncer.EXPANSION_VISIBLE)
+ setPanelExpansion(KeyguardBouncerConstants.EXPANSION_VISIBLE)
}
if (resumeBouncer) {
@@ -204,14 +204,14 @@
}
if (
- expansion == KeyguardBouncer.EXPANSION_VISIBLE &&
- oldExpansion != KeyguardBouncer.EXPANSION_VISIBLE
+ expansion == KeyguardBouncerConstants.EXPANSION_VISIBLE &&
+ oldExpansion != KeyguardBouncerConstants.EXPANSION_VISIBLE
) {
falsingCollector.onBouncerShown()
primaryBouncerCallbackInteractor.dispatchFullyShown()
} else if (
- expansion == KeyguardBouncer.EXPANSION_HIDDEN &&
- oldExpansion != KeyguardBouncer.EXPANSION_HIDDEN
+ expansion == KeyguardBouncerConstants.EXPANSION_HIDDEN &&
+ oldExpansion != KeyguardBouncerConstants.EXPANSION_HIDDEN
) {
/*
* There are cases where #hide() was not invoked, such as when
@@ -222,8 +222,8 @@
DejankUtils.postAfterTraversal { primaryBouncerCallbackInteractor.dispatchReset() }
primaryBouncerCallbackInteractor.dispatchFullyHidden()
} else if (
- expansion != KeyguardBouncer.EXPANSION_VISIBLE &&
- oldExpansion == KeyguardBouncer.EXPANSION_VISIBLE
+ expansion != KeyguardBouncerConstants.EXPANSION_VISIBLE &&
+ oldExpansion == KeyguardBouncerConstants.EXPANSION_VISIBLE
) {
primaryBouncerCallbackInteractor.dispatchStartingToHide()
repository.setPrimaryStartingToHide(true)
@@ -303,7 +303,7 @@
fun isFullyShowing(): Boolean {
return (repository.primaryBouncerShowingSoon.value ||
repository.primaryBouncerVisible.value) &&
- repository.panelExpansionAmount.value == KeyguardBouncer.EXPANSION_VISIBLE &&
+ repository.panelExpansionAmount.value == KeyguardBouncerConstants.EXPANSION_VISIBLE &&
repository.primaryBouncerStartingDisappearAnimation.value == null
}
@@ -315,8 +315,8 @@
/** If bouncer expansion is between 0f and 1f non-inclusive. */
fun isInTransit(): Boolean {
return repository.primaryBouncerShowingSoon.value ||
- repository.panelExpansionAmount.value != KeyguardBouncer.EXPANSION_HIDDEN &&
- repository.panelExpansionAmount.value != KeyguardBouncer.EXPANSION_VISIBLE
+ repository.panelExpansionAmount.value != KeyguardBouncerConstants.EXPANSION_HIDDEN &&
+ repository.panelExpansionAmount.value != KeyguardBouncerConstants.EXPANSION_VISIBLE
}
/** Return whether bouncer is animating away. */
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/constants/KeyguardBouncerConstants.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/constants/KeyguardBouncerConstants.kt
new file mode 100644
index 0000000..bb5ac84
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/constants/KeyguardBouncerConstants.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.keyguard.shared.constants
+
+object KeyguardBouncerConstants {
+ /**
+ * Values for the bouncer expansion represented as the panel expansion. Panel expansion 1f =
+ * panel fully showing = bouncer fully hidden Panel expansion 0f = panel fully hiding = bouncer
+ * fully showing
+ */
+ const val EXPANSION_HIDDEN = 1f
+ const val EXPANSION_VISIBLE = 0f
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardQuickAffordancePickerRepresentation.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardQuickAffordancePickerRepresentation.kt
index 7d13359..e7e9159 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardQuickAffordancePickerRepresentation.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardQuickAffordancePickerRepresentation.kt
@@ -17,6 +17,7 @@
package com.android.systemui.keyguard.shared.model
+import android.content.Intent
import androidx.annotation.DrawableRes
/**
@@ -45,4 +46,7 @@
* user to a destination where they can re-enable it.
*/
val actionComponentName: String? = null,
+
+ /** Optional [Intent] to use to start an activity to configure this affordance. */
+ val configureIntent: Intent? = null,
)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt
index 0e4058b..9d8bf7d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt
@@ -45,7 +45,6 @@
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.statusbar.VibratorHelper
-import com.android.systemui.util.kotlin.pairwise
import kotlin.math.pow
import kotlin.math.sqrt
import kotlin.time.Duration.Companion.milliseconds
@@ -129,18 +128,6 @@
}
launch {
- viewModel.startButton
- .map { it.isActivated }
- .pairwise()
- .collect { (prev, next) ->
- when {
- !prev && next -> vibratorHelper?.vibrate(Vibrations.Activated)
- prev && !next -> vibratorHelper?.vibrate(Vibrations.Deactivated)
- }
- }
- }
-
- launch {
viewModel.endButton.collect { buttonModel ->
updateButton(
view = endButton,
@@ -153,18 +140,6 @@
}
launch {
- viewModel.endButton
- .map { it.isActivated }
- .pairwise()
- .collect { (prev, next) ->
- when {
- !prev && next -> vibratorHelper?.vibrate(Vibrations.Activated)
- prev && !next -> vibratorHelper?.vibrate(Vibrations.Deactivated)
- }
- }
- }
-
- launch {
viewModel.isOverlayContainerVisible.collect { isVisible ->
overlayContainer.visibility =
if (isVisible) {
@@ -383,6 +358,13 @@
.setDuration(longPressDurationMs)
.withEndAction {
view.setOnClickListener {
+ vibratorHelper?.vibrate(
+ if (viewModel.isActivated) {
+ Vibrations.Activated
+ } else {
+ Vibrations.Deactivated
+ }
+ )
viewModel.onClicked(
KeyguardQuickAffordanceViewModel.OnClickedParameters(
configKey = viewModel.configKey,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt
index f772b17..5e46c5d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt
@@ -19,6 +19,7 @@
import android.view.KeyEvent
import android.view.View
import android.view.ViewGroup
+import android.window.OnBackAnimationCallback
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import com.android.internal.policy.SystemBarUtils
@@ -27,10 +28,10 @@
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.dagger.KeyguardBouncerComponent
import com.android.systemui.keyguard.data.BouncerViewDelegate
+import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.plugins.ActivityStarter
-import com.android.systemui.statusbar.phone.KeyguardBouncer.EXPANSION_VISIBLE
import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.launch
@@ -55,6 +56,10 @@
mode == KeyguardSecurityModel.SecurityMode.SimPuk
}
+ override fun getBackCallback(): OnBackAnimationCallback {
+ return hostViewController.backCallback
+ }
+
override fun shouldDismissOnMenuPressed(): Boolean {
return hostViewController.shouldEnableMenuKey()
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt
index e164f5d..6627865 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt
@@ -22,10 +22,14 @@
import com.android.systemui.keyguard.domain.interactor.FromDreamingTransitionInteractor.Companion.TO_LOCKSCREEN_DURATION
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.AnimationParams
+import com.android.systemui.keyguard.shared.model.TransitionState.CANCELED
+import com.android.systemui.keyguard.shared.model.TransitionState.FINISHED
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.merge
/**
* Breaks down DREAMING->LOCKSCREEN transition into discrete steps for corresponding views to
@@ -49,9 +53,15 @@
/** Lockscreen views y-translation */
fun lockscreenTranslationY(translatePx: Int): Flow<Float> {
- return flowForAnimation(LOCKSCREEN_TRANSLATION_Y).map { value ->
- -translatePx + (EMPHASIZED_DECELERATE.getInterpolation(value) * translatePx)
- }
+ return merge(
+ flowForAnimation(LOCKSCREEN_TRANSLATION_Y).map { value ->
+ -translatePx + (EMPHASIZED_DECELERATE.getInterpolation(value) * translatePx)
+ },
+ // On end, reset the translation to 0
+ interactor.dreamingToLockscreenTransition
+ .filter { it.transitionState == FINISHED || it.transitionState == CANCELED }
+ .map { 0f }
+ )
}
/** Lockscreen views alpha */
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModel.kt
new file mode 100644
index 0000000..5a47960
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModel.kt
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import com.android.systemui.animation.Interpolators.EMPHASIZED_ACCELERATE
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.domain.interactor.FromGoneTransitionInteractor.Companion.TO_DREAMING_DURATION
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.shared.model.AnimationParams
+import com.android.systemui.keyguard.shared.model.TransitionState.CANCELED
+import com.android.systemui.keyguard.shared.model.TransitionState.FINISHED
+import javax.inject.Inject
+import kotlin.time.Duration.Companion.milliseconds
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.merge
+
+/** Breaks down GONE->DREAMING transition into discrete steps for corresponding views to consume. */
+@SysUISingleton
+class GoneToDreamingTransitionViewModel
+@Inject
+constructor(
+ private val interactor: KeyguardTransitionInteractor,
+) {
+
+ /** Lockscreen views y-translation */
+ fun lockscreenTranslationY(translatePx: Int): Flow<Float> {
+ return merge(
+ flowForAnimation(LOCKSCREEN_TRANSLATION_Y).map { value ->
+ (EMPHASIZED_ACCELERATE.getInterpolation(value) * translatePx)
+ },
+ // On end, reset the translation to 0
+ interactor.goneToDreamingTransition
+ .filter { it.transitionState == FINISHED || it.transitionState == CANCELED }
+ .map { 0f }
+ )
+ }
+
+ /** Lockscreen views alpha */
+ val lockscreenAlpha: Flow<Float> = flowForAnimation(LOCKSCREEN_ALPHA).map { 1f - it }
+
+ private fun flowForAnimation(params: AnimationParams): Flow<Float> {
+ return interactor.transitionStepAnimation(
+ interactor.goneToDreamingTransition,
+ params,
+ totalDuration = TO_DREAMING_DURATION
+ )
+ }
+
+ companion object {
+ val LOCKSCREEN_TRANSLATION_Y = AnimationParams(duration = 500.milliseconds)
+ val LOCKSCREEN_ALPHA = AnimationParams(duration = 250.milliseconds)
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt
index e5d4e49..c6002d6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt
@@ -20,9 +20,9 @@
import com.android.systemui.keyguard.data.BouncerView
import com.android.systemui.keyguard.data.BouncerViewDelegate
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor
+import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE
import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
import com.android.systemui.keyguard.shared.model.KeyguardBouncerModel
-import com.android.systemui.statusbar.phone.KeyguardBouncer.EXPANSION_VISIBLE
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.filter
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModel.kt
index d48f87d..e05adbd 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModel.kt
@@ -21,7 +21,8 @@
import com.android.systemui.keyguard.domain.interactor.FromLockscreenTransitionInteractor.Companion.TO_DREAMING_DURATION
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.AnimationParams
-import com.android.systemui.keyguard.shared.model.TransitionState
+import com.android.systemui.keyguard.shared.model.TransitionState.CANCELED
+import com.android.systemui.keyguard.shared.model.TransitionState.FINISHED
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
import kotlinx.coroutines.flow.Flow
@@ -48,7 +49,7 @@
},
// On end, reset the translation to 0
interactor.lockscreenToDreamingTransition
- .filter { step -> step.transitionState == TransitionState.FINISHED }
+ .filter { it.transitionState == FINISHED || it.transitionState == CANCELED }
.map { 0f }
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt b/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt
index e364918..d69ac7f 100644
--- a/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt
+++ b/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt
@@ -145,7 +145,7 @@
* └───────────────┴───────────────────┴──────────────┴─────────────────┘
* ```
*/
-private class ViewLifecycleOwner(
+class ViewLifecycleOwner(
private val view: View,
) : LifecycleOwner {
diff --git a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
index 7a90a74..7ccc43c 100644
--- a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
@@ -29,6 +29,18 @@
private val dumpManager: DumpManager,
private val systemClock: SystemClock,
) {
+ private val existingBuffers = mutableMapOf<String, TableLogBuffer>()
+
+ /**
+ * Creates a new [TableLogBuffer]. This method should only be called from static contexts, where
+ * it is guaranteed only to be created one time. See [getOrCreate] for a cache-aware method of
+ * obtaining a buffer.
+ *
+ * @param name a unique table name
+ * @param maxSize the buffer max size. See [adjustMaxSize]
+ *
+ * @return a new [TableLogBuffer] registered with [DumpManager]
+ */
fun create(
name: String,
maxSize: Int,
@@ -37,4 +49,23 @@
dumpManager.registerNormalDumpable(name, tableBuffer)
return tableBuffer
}
+
+ /**
+ * Log buffers are retained indefinitely by [DumpManager], so that they can be represented in
+ * bugreports. Because of this, many of them are created statically in the Dagger graph.
+ *
+ * In the case where you have to create a logbuffer with a name only known at runtime, this
+ * method can be used to lazily create a table log buffer which is then cached for reuse.
+ *
+ * @return a [TableLogBuffer] suitable for reuse
+ */
+ fun getOrCreate(
+ name: String,
+ maxSize: Int,
+ ): TableLogBuffer =
+ existingBuffers.getOrElse(name) {
+ val buffer = create(name, maxSize)
+ existingBuffers[name] = buffer
+ buffer
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt
index ceb4845..a692ad7 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt
@@ -18,6 +18,7 @@
import android.app.ActivityOptions
import android.content.Intent
import android.content.res.Configuration
+import android.content.res.Resources
import android.media.projection.IMediaProjection
import android.media.projection.MediaProjectionManager.EXTRA_MEDIA_PROJECTION
import android.os.Binder
@@ -27,6 +28,7 @@
import android.os.UserHandle
import android.view.ViewGroup
import com.android.internal.annotations.VisibleForTesting
+import com.android.internal.app.AbstractMultiProfilePagerAdapter.MyUserIdProvider
import com.android.internal.app.ChooserActivity
import com.android.internal.app.ResolverListController
import com.android.internal.app.chooser.NotSelectableTargetInfo
@@ -59,16 +61,12 @@
private lateinit var configurationController: ConfigurationController
private lateinit var controller: MediaProjectionAppSelectorController
private lateinit var recentsViewController: MediaProjectionRecentsViewController
+ private lateinit var component: MediaProjectionAppSelectorComponent
override fun getLayoutResource() = R.layout.media_projection_app_selector
public override fun onCreate(bundle: Bundle?) {
- val component =
- componentFactory.create(
- activity = this,
- view = this,
- resultHandler = this
- )
+ component = componentFactory.create(activity = this, view = this, resultHandler = this)
// Create a separate configuration controller for this activity as the configuration
// might be different from the global one
@@ -76,11 +74,12 @@
controller = component.controller
recentsViewController = component.recentsViewController
- val queryIntent = Intent(Intent.ACTION_MAIN).apply { addCategory(Intent.CATEGORY_LAUNCHER) }
- intent.putExtra(Intent.EXTRA_INTENT, queryIntent)
+ intent.configureChooserIntent(
+ resources,
+ component.hostUserHandle,
+ component.personalProfileUserHandle
+ )
- val title = getString(R.string.media_projection_permission_app_selector_title)
- intent.putExtra(Intent.EXTRA_TITLE, title)
super.onCreate(bundle)
controller.init()
}
@@ -183,6 +182,13 @@
override fun shouldShowContentPreview() = true
+ override fun shouldShowContentPreviewWhenEmpty(): Boolean = true
+
+ override fun createMyUserIdProvider(): MyUserIdProvider =
+ object : MyUserIdProvider() {
+ override fun getMyUserId(): Int = component.hostUserHandle.identifier
+ }
+
override fun createContentPreviewView(parent: ViewGroup): ViewGroup =
recentsViewController.createView(parent)
@@ -193,6 +199,34 @@
* instance through activity result.
*/
const val EXTRA_CAPTURE_REGION_RESULT_RECEIVER = "capture_region_result_receiver"
+
+ /** UID of the app that originally launched the media projection flow (host app user) */
+ const val EXTRA_HOST_APP_USER_HANDLE = "launched_from_user_handle"
const val KEY_CAPTURE_TARGET = "capture_region"
+
+ /** Set up intent for the [ChooserActivity] */
+ private fun Intent.configureChooserIntent(
+ resources: Resources,
+ hostUserHandle: UserHandle,
+ personalProfileUserHandle: UserHandle
+ ) {
+ // Specify the query intent to show icons for all apps on the chooser screen
+ val queryIntent =
+ Intent(Intent.ACTION_MAIN).apply { addCategory(Intent.CATEGORY_LAUNCHER) }
+ putExtra(Intent.EXTRA_INTENT, queryIntent)
+
+ // Update the title of the chooser
+ val title = resources.getString(R.string.media_projection_permission_app_selector_title)
+ putExtra(Intent.EXTRA_TITLE, title)
+
+ // Select host app's profile tab by default
+ val selectedProfile =
+ if (hostUserHandle == personalProfileUserHandle) {
+ PROFILE_PERSONAL
+ } else {
+ PROFILE_WORK
+ }
+ putExtra(EXTRA_SELECTED_PROFILE, selectedProfile)
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
index bfa67a8..d830fc4 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
@@ -22,6 +22,7 @@
import static com.android.systemui.screenrecord.ScreenShareOptionKt.SINGLE_APP;
import android.app.Activity;
+import android.app.ActivityManager;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
@@ -35,6 +36,7 @@
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.UserHandle;
import android.text.BidiFormatter;
import android.text.SpannableString;
import android.text.TextPaint;
@@ -208,8 +210,14 @@
final Intent intent = new Intent(this, MediaProjectionAppSelectorActivity.class);
intent.putExtra(MediaProjectionManager.EXTRA_MEDIA_PROJECTION,
projection.asBinder());
+ intent.putExtra(MediaProjectionAppSelectorActivity.EXTRA_HOST_APP_USER_HANDLE,
+ UserHandle.getUserHandleForUid(getLaunchedFromUid()));
intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
- startActivity(intent);
+
+ // Start activity from the current foreground user to avoid creating a separate
+ // SystemUI process without access to recent tasks because it won't have
+ // WM Shell running inside.
+ startActivityAsUser(intent, UserHandle.of(ActivityManager.getCurrentUser()));
}
} catch (RemoteException e) {
Log.e(TAG, "Error granting projection permission", e);
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/models/player/MediaData.kt b/packages/SystemUI/src/com/android/systemui/media/controls/models/player/MediaData.kt
index f006442..be18cbe 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/models/player/MediaData.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/models/player/MediaData.kt
@@ -88,7 +88,10 @@
val instanceId: InstanceId,
/** The UID of the app, used for logging */
- val appUid: Int
+ val appUid: Int,
+
+ /** Whether explicit indicator exists */
+ val isExplicit: Boolean = false,
) {
companion object {
/** Media is playing on the local device */
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/models/player/MediaViewHolder.kt b/packages/SystemUI/src/com/android/systemui/media/controls/models/player/MediaViewHolder.kt
index a8f39fa9a..1c8bfd1 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/models/player/MediaViewHolder.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/models/player/MediaViewHolder.kt
@@ -24,6 +24,7 @@
import android.widget.SeekBar
import android.widget.TextView
import androidx.constraintlayout.widget.Barrier
+import com.android.internal.widget.CachingIconView
import com.android.systemui.R
import com.android.systemui.media.controls.models.GutsViewHolder
import com.android.systemui.surfaceeffects.ripple.MultiRippleView
@@ -44,6 +45,7 @@
val appIcon = itemView.requireViewById<ImageView>(R.id.icon)
val titleText = itemView.requireViewById<TextView>(R.id.header_title)
val artistText = itemView.requireViewById<TextView>(R.id.header_artist)
+ val explicitIndicator = itemView.requireViewById<CachingIconView>(R.id.media_explicit_indicator)
// Output switcher
val seamless = itemView.requireViewById<ViewGroup>(R.id.media_seamless)
@@ -123,6 +125,7 @@
R.id.app_name,
R.id.header_title,
R.id.header_artist,
+ R.id.media_explicit_indicator,
R.id.media_seamless,
R.id.media_progress_bar,
R.id.actionPlayPause,
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt
index 1cc8a13..6a5e725 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt
@@ -46,6 +46,7 @@
import android.os.UserHandle
import android.provider.Settings
import android.service.notification.StatusBarNotification
+import android.support.v4.media.MediaMetadataCompat
import android.text.TextUtils
import android.util.Log
import androidx.media.utils.MediaConstants
@@ -661,6 +662,10 @@
val currentEntry = mediaEntries.get(packageName)
val instanceId = currentEntry?.instanceId ?: logger.getNewInstanceId()
val appUid = currentEntry?.appUid ?: Process.INVALID_UID
+ val isExplicit =
+ desc.extras?.getLong(MediaConstants.METADATA_KEY_IS_EXPLICIT) ==
+ MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT &&
+ mediaFlags.isExplicitIndicatorEnabled()
val mediaAction = getResumeMediaAction(resumeAction)
val lastActive = systemClock.elapsedRealtime()
@@ -690,7 +695,8 @@
hasCheckedForResume = true,
lastActive = lastActive,
instanceId = instanceId,
- appUid = appUid
+ appUid = appUid,
+ isExplicit = isExplicit,
)
)
}
@@ -751,6 +757,15 @@
song = HybridGroupManager.resolveTitle(notif)
}
+ // Explicit Indicator
+ var isExplicit = false
+ if (mediaFlags.isExplicitIndicatorEnabled()) {
+ val mediaMetadataCompat = MediaMetadataCompat.fromMediaMetadata(metadata)
+ isExplicit =
+ mediaMetadataCompat?.getLong(MediaConstants.METADATA_KEY_IS_EXPLICIT) ==
+ MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT
+ }
+
// Artist name
var artist: CharSequence? = metadata?.getString(MediaMetadata.METADATA_KEY_ARTIST)
if (artist == null) {
@@ -849,10 +864,11 @@
notificationKey = key,
hasCheckedForResume = hasCheckedForResume,
isPlaying = isPlaying,
- isClearable = sbn.isClearable(),
+ isClearable = !sbn.isOngoing,
lastActive = lastActive,
instanceId = instanceId,
- appUid = appUid
+ appUid = appUid,
+ isExplicit = isExplicit,
)
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/KeyguardMediaController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/KeyguardMediaController.kt
index 899148b..8f1c904 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/KeyguardMediaController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/KeyguardMediaController.kt
@@ -130,7 +130,12 @@
private var splitShadeContainer: ViewGroup? = null
/** Track the media player setting status on lock screen. */
- private var allowMediaPlayerOnLockScreen: Boolean = true
+ private var allowMediaPlayerOnLockScreen: Boolean =
+ secureSettings.getBoolForUser(
+ Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN,
+ true,
+ UserHandle.USER_CURRENT
+ )
private val lockScreenMediaPlayerUri =
secureSettings.getUriFor(Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN)
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt
index d5558b2..e7f7647 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt
@@ -94,7 +94,7 @@
private var currentCarouselWidth: Int = 0
/** The current height of the carousel */
- private var currentCarouselHeight: Int = 0
+ @VisibleForTesting var currentCarouselHeight: Int = 0
/** Are we currently showing only active players */
private var currentlyShowingOnlyActive: Boolean = false
@@ -128,14 +128,14 @@
/** The measured height of the carousel */
private var carouselMeasureHeight: Int = 0
private var desiredHostState: MediaHostState? = null
- private val mediaCarousel: MediaScrollView
+ @VisibleForTesting var mediaCarousel: MediaScrollView
val mediaCarouselScrollHandler: MediaCarouselScrollHandler
val mediaFrame: ViewGroup
@VisibleForTesting
lateinit var settingsButton: View
private set
private val mediaContent: ViewGroup
- @VisibleForTesting val pageIndicator: PageIndicator
+ @VisibleForTesting var pageIndicator: PageIndicator
private val visualStabilityCallback: OnReorderingAllowedListener
private var needsReordering: Boolean = false
private var keysNeedRemoval = mutableSetOf<String>()
@@ -160,25 +160,20 @@
}
companion object {
- const val ANIMATION_BASE_DURATION = 2200f
- const val DURATION = 167f
- const val DETAILS_DELAY = 1067f
- const val CONTROLS_DELAY = 1400f
- const val PAGINATION_DELAY = 1900f
- const val MEDIATITLES_DELAY = 1000f
- const val MEDIACONTAINERS_DELAY = 967f
val TRANSFORM_BEZIER = PathInterpolator(0.68F, 0F, 0F, 1F)
- val REVERSE_BEZIER = PathInterpolator(0F, 0.68F, 1F, 0F)
- fun calculateAlpha(squishinessFraction: Float, delay: Float, duration: Float): Float {
- val transformStartFraction = delay / ANIMATION_BASE_DURATION
- val transformDurationFraction = duration / ANIMATION_BASE_DURATION
- val squishinessToTime = REVERSE_BEZIER.getInterpolation(squishinessFraction)
- return MathUtils.constrain(
- (squishinessToTime - transformStartFraction) / transformDurationFraction,
- 0F,
- 1F
- )
+ fun calculateAlpha(
+ squishinessFraction: Float,
+ startPosition: Float,
+ endPosition: Float
+ ): Float {
+ val transformFraction =
+ MathUtils.constrain(
+ (squishinessFraction - startPosition) / (endPosition - startPosition),
+ 0F,
+ 1F
+ )
+ return TRANSFORM_BEZIER.getInterpolation(transformFraction)
}
}
@@ -813,7 +808,12 @@
val squishFraction = hostStates[currentEndLocation]?.squishFraction ?: 1.0F
val endAlpha =
(if (endIsVisible) 1.0f else 0.0f) *
- calculateAlpha(squishFraction, PAGINATION_DELAY, DURATION)
+ calculateAlpha(
+ squishFraction,
+ (pageIndicator.translationY + pageIndicator.height) /
+ mediaCarousel.measuredHeight,
+ 1F
+ )
var alpha = 1.0f
if (!endIsVisible || !startIsVisible) {
var progress = currentTransitionProgress
@@ -839,7 +839,8 @@
pageIndicator.translationX = translationX + mediaCarouselScrollHandler.contentTranslation
val layoutParams = pageIndicator.layoutParams as ViewGroup.MarginLayoutParams
pageIndicator.translationY =
- (currentCarouselHeight - pageIndicator.height - layoutParams.bottomMargin).toFloat()
+ (mediaCarousel.measuredHeight - pageIndicator.height - layoutParams.bottomMargin)
+ .toFloat()
}
/** Update the dimension of this carousel. */
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
index ee0147f..39dd733 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
@@ -51,7 +51,6 @@
import android.os.Trace;
import android.text.TextUtils;
import android.util.Log;
-import android.util.Pair;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
@@ -69,6 +68,7 @@
import com.android.internal.graphics.ColorUtils;
import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.logging.InstanceId;
+import com.android.internal.widget.CachingIconView;
import com.android.settingslib.widget.AdaptiveIcon;
import com.android.systemui.ActivityIntentHelper;
import com.android.systemui.R;
@@ -112,6 +112,7 @@
import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseController;
import com.android.systemui.util.ColorUtilKt;
import com.android.systemui.util.animation.TransitionLayout;
+import com.android.systemui.util.concurrency.DelayableExecutor;
import com.android.systemui.util.time.SystemClock;
import dagger.Lazy;
@@ -123,6 +124,7 @@
import javax.inject.Inject;
+import kotlin.Triple;
import kotlin.Unit;
/**
@@ -168,10 +170,13 @@
R.id.action1
);
+ // Time in millis for playing turbulence noise that is played after a touch ripple.
+ @VisibleForTesting static final long TURBULENCE_NOISE_PLAY_DURATION = 7500L;
+
private final SeekBarViewModel mSeekBarViewModel;
private SeekBarObserver mSeekBarObserver;
protected final Executor mBackgroundExecutor;
- private final Executor mMainExecutor;
+ private final DelayableExecutor mMainExecutor;
private final ActivityStarter mActivityStarter;
private final BroadcastSender mBroadcastSender;
@@ -224,10 +229,10 @@
private String mSwitchBroadcastApp;
private MultiRippleController mMultiRippleController;
private TurbulenceNoiseController mTurbulenceNoiseController;
- private FeatureFlags mFeatureFlags;
- private TurbulenceNoiseAnimationConfig mTurbulenceNoiseAnimationConfig = null;
+ private final FeatureFlags mFeatureFlags;
+ private TurbulenceNoiseAnimationConfig mTurbulenceNoiseAnimationConfig;
@VisibleForTesting
- MultiRippleController.Companion.RipplesFinishedListener mRipplesFinishedListener = null;
+ MultiRippleController.Companion.RipplesFinishedListener mRipplesFinishedListener;
/**
* Initialize a new control panel
@@ -241,7 +246,7 @@
public MediaControlPanel(
Context context,
@Background Executor backgroundExecutor,
- @Main Executor mainExecutor,
+ @Main DelayableExecutor mainExecutor,
ActivityStarter activityStarter,
BroadcastSender broadcastSender,
MediaViewController mediaViewController,
@@ -400,10 +405,11 @@
TextView titleText = mMediaViewHolder.getTitleText();
TextView artistText = mMediaViewHolder.getArtistText();
+ CachingIconView explicitIndicator = mMediaViewHolder.getExplicitIndicator();
AnimatorSet enter = loadAnimator(R.anim.media_metadata_enter,
- Interpolators.EMPHASIZED_DECELERATE, titleText, artistText);
+ Interpolators.EMPHASIZED_DECELERATE, titleText, artistText, explicitIndicator);
AnimatorSet exit = loadAnimator(R.anim.media_metadata_exit,
- Interpolators.EMPHASIZED_ACCELERATE, titleText, artistText);
+ Interpolators.EMPHASIZED_ACCELERATE, titleText, artistText, explicitIndicator);
MultiRippleView multiRippleView = vh.getMultiRippleView();
mMultiRippleController = new MultiRippleController(multiRippleView);
@@ -411,10 +417,12 @@
if (mFeatureFlags.isEnabled(Flags.UMO_TURBULENCE_NOISE)) {
mRipplesFinishedListener = () -> {
if (mTurbulenceNoiseAnimationConfig == null) {
- mTurbulenceNoiseAnimationConfig = createLingeringNoiseAnimation();
+ mTurbulenceNoiseAnimationConfig = createTurbulenceNoiseAnimation();
}
// Color will be correctly updated in ColorSchemeTransition.
mTurbulenceNoiseController.play(mTurbulenceNoiseAnimationConfig);
+ mMainExecutor.executeDelayed(
+ mTurbulenceNoiseController::finish, TURBULENCE_NOISE_PLAY_DURATION);
};
mMultiRippleController.addRipplesFinishedListener(mRipplesFinishedListener);
}
@@ -668,11 +676,15 @@
private boolean bindSongMetadata(MediaData data) {
TextView titleText = mMediaViewHolder.getTitleText();
TextView artistText = mMediaViewHolder.getArtistText();
+ ConstraintSet expandedSet = mMediaViewController.getExpandedLayout();
+ ConstraintSet collapsedSet = mMediaViewController.getCollapsedLayout();
return mMetadataAnimationHandler.setNext(
- Pair.create(data.getSong(), data.getArtist()),
+ new Triple(data.getSong(), data.getArtist(), data.isExplicit()),
() -> {
titleText.setText(data.getSong());
artistText.setText(data.getArtist());
+ setVisibleAndAlpha(expandedSet, R.id.media_explicit_indicator, data.isExplicit());
+ setVisibleAndAlpha(collapsedSet, R.id.media_explicit_indicator, data.isExplicit());
// refreshState is required here to resize the text views (and prevent ellipsis)
mMediaViewController.refreshState();
@@ -1060,7 +1072,7 @@
);
}
- private TurbulenceNoiseAnimationConfig createLingeringNoiseAnimation() {
+ private TurbulenceNoiseAnimationConfig createTurbulenceNoiseAnimation() {
return new TurbulenceNoiseAnimationConfig(
TurbulenceNoiseAnimationConfig.DEFAULT_NOISE_GRID_COUNT,
TurbulenceNoiseAnimationConfig.DEFAULT_LUMINOSITY_MULTIPLIER,
@@ -1075,7 +1087,9 @@
/* width= */ mMediaViewHolder.getMultiRippleView().getWidth(),
/* height= */ mMediaViewHolder.getMultiRippleView().getHeight(),
TurbulenceNoiseAnimationConfig.DEFAULT_MAX_DURATION_IN_MILLIS,
+ /* easeInDuration= */
TurbulenceNoiseAnimationConfig.DEFAULT_EASING_DURATION_IN_MILLIS,
+ /* easeOutDuration= */
TurbulenceNoiseAnimationConfig.DEFAULT_EASING_DURATION_IN_MILLIS,
this.getContext().getResources().getDisplayMetrics().density,
BlendMode.PLUS,
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt
index 3224213..2ec7be6 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt
@@ -24,11 +24,6 @@
import com.android.systemui.media.controls.models.GutsViewHolder
import com.android.systemui.media.controls.models.player.MediaViewHolder
import com.android.systemui.media.controls.models.recommendation.RecommendationViewHolder
-import com.android.systemui.media.controls.ui.MediaCarouselController.Companion.CONTROLS_DELAY
-import com.android.systemui.media.controls.ui.MediaCarouselController.Companion.DETAILS_DELAY
-import com.android.systemui.media.controls.ui.MediaCarouselController.Companion.DURATION
-import com.android.systemui.media.controls.ui.MediaCarouselController.Companion.MEDIACONTAINERS_DELAY
-import com.android.systemui.media.controls.ui.MediaCarouselController.Companion.MEDIATITLES_DELAY
import com.android.systemui.media.controls.ui.MediaCarouselController.Companion.calculateAlpha
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.util.animation.MeasurementOutput
@@ -36,6 +31,8 @@
import com.android.systemui.util.animation.TransitionLayoutController
import com.android.systemui.util.animation.TransitionViewState
import com.android.systemui.util.traceSection
+import java.lang.Float.max
+import java.lang.Float.min
import javax.inject.Inject
/**
@@ -80,6 +77,7 @@
setOf(
R.id.header_title,
R.id.header_artist,
+ R.id.media_explicit_indicator,
R.id.actionPlayPause,
)
@@ -304,42 +302,109 @@
val squishedViewState = viewState.copy()
val squishedHeight = (squishedViewState.measureHeight * squishFraction).toInt()
squishedViewState.height = squishedHeight
- controlIds.forEach { id ->
- squishedViewState.widgetStates.get(id)?.let { state ->
- state.alpha = calculateAlpha(squishFraction, CONTROLS_DELAY, DURATION)
- }
- }
-
- detailIds.forEach { id ->
- squishedViewState.widgetStates.get(id)?.let { state ->
- state.alpha = calculateAlpha(squishFraction, DETAILS_DELAY, DURATION)
- }
- }
-
// We are not overriding the squishedViewStates height but only the children to avoid
// them remeasuring the whole view. Instead it just remains as the original size
backgroundIds.forEach { id ->
- squishedViewState.widgetStates.get(id)?.let { state ->
- state.height = squishedHeight
- }
+ squishedViewState.widgetStates.get(id)?.let { state -> state.height = squishedHeight }
}
- RecommendationViewHolder.mediaContainersIds.forEach { id ->
- squishedViewState.widgetStates.get(id)?.let { state ->
- state.alpha = calculateAlpha(squishFraction, MEDIACONTAINERS_DELAY, DURATION)
- }
- }
-
- RecommendationViewHolder.mediaTitlesAndSubtitlesIds.forEach { id ->
- squishedViewState.widgetStates.get(id)?.let { state ->
- state.alpha = calculateAlpha(squishFraction, MEDIATITLES_DELAY, DURATION)
- }
- }
-
+ // media player
+ val controlsTop =
+ calculateWidgetGroupAlphaForSquishiness(
+ controlIds,
+ squishedViewState.measureHeight.toFloat(),
+ squishedViewState,
+ squishFraction
+ )
+ calculateWidgetGroupAlphaForSquishiness(
+ detailIds,
+ controlsTop,
+ squishedViewState,
+ squishFraction
+ )
+ // recommendation card
+ val titlesTop =
+ calculateWidgetGroupAlphaForSquishiness(
+ RecommendationViewHolder.mediaTitlesAndSubtitlesIds,
+ squishedViewState.measureHeight.toFloat(),
+ squishedViewState,
+ squishFraction
+ )
+ calculateWidgetGroupAlphaForSquishiness(
+ RecommendationViewHolder.mediaContainersIds,
+ titlesTop,
+ squishedViewState,
+ squishFraction
+ )
return squishedViewState
}
/**
+ * This function is to make each widget in UMO disappear before being clipped by squished UMO
+ *
+ * The general rule is that widgets in UMO has been divided into several groups, and widgets in
+ * one group have the same alpha during squishing It will change from alpha 0.0 when the visible
+ * bottom of UMO reach the bottom of this group It will change to alpha 1.0 when the visible
+ * bottom of UMO reach the top of the group below e.g.Album title, artist title and play-pause
+ * button will change alpha together.
+ * ```
+ * And their alpha becomes 1.0 when the visible bottom of UMO reach the top of controls,
+ * including progress bar, next button, previous button
+ * ```
+ * widgetGroupIds: a group of widgets have same state during UMO is squished,
+ * ```
+ * e.g. Album title, artist title and play-pause button
+ * ```
+ * groupEndPosition: the height of UMO, when the height reaches this value,
+ * ```
+ * widgets in this group should have 1.0 as alpha
+ * e.g., the group of album title, artist title and play-pause button will become fully
+ * visible when the height of UMO reaches the top of controls group
+ * (progress bar, previous button and next button)
+ * ```
+ * squishedViewState: hold the widgetState of each widget, which will be modified
+ * squishFraction: the squishFraction of UMO
+ */
+ private fun calculateWidgetGroupAlphaForSquishiness(
+ widgetGroupIds: Set<Int>,
+ groupEndPosition: Float,
+ squishedViewState: TransitionViewState,
+ squishFraction: Float
+ ): Float {
+ val nonsquishedHeight = squishedViewState.measureHeight
+ var groupTop = squishedViewState.measureHeight.toFloat()
+ var groupBottom = 0F
+ widgetGroupIds.forEach { id ->
+ squishedViewState.widgetStates.get(id)?.let { state ->
+ groupTop = min(groupTop, state.y)
+ groupBottom = max(groupBottom, state.y + state.height)
+ }
+ }
+ // startPosition means to the height of squished UMO where the widget alpha should start
+ // changing from 0.0
+ // generally, it equals to the bottom of widgets, so that we can meet the requirement that
+ // widget should not go beyond the bounds of background
+ // endPosition means to the height of squished UMO where the widget alpha should finish
+ // changing alpha to 1.0
+ var startPosition = groupBottom
+ val endPosition = groupEndPosition
+ if (startPosition == endPosition) {
+ startPosition = (endPosition - 0.2 * (groupBottom - groupTop)).toFloat()
+ }
+ widgetGroupIds.forEach { id ->
+ squishedViewState.widgetStates.get(id)?.let { state ->
+ state.alpha =
+ calculateAlpha(
+ squishFraction,
+ startPosition / nonsquishedHeight,
+ endPosition / nonsquishedHeight
+ )
+ }
+ }
+ return groupTop // used for the widget group above this group
+ }
+
+ /**
* Obtain a new viewState for a given media state. This usually returns a cached state, but if
* it's not available, it will recreate one by measuring, which may be expensive.
*/
@@ -544,11 +609,13 @@
overrideSize?.let {
// To be safe we're using a maximum here. The override size should always be set
// properly though.
- if (result.measureHeight != it.measuredHeight
- || result.measureWidth != it.measuredWidth) {
+ if (
+ result.measureHeight != it.measuredHeight || result.measureWidth != it.measuredWidth
+ ) {
result.measureHeight = Math.max(it.measuredHeight, result.measureHeight)
result.measureWidth = Math.max(it.measuredWidth, result.measureWidth)
- // The measureHeight and the shown height should both be set to the overridden height
+ // The measureHeight and the shown height should both be set to the overridden
+ // height
result.height = result.measureHeight
result.width = result.measureWidth
// Make sure all background views are also resized such that their size is correct
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
index 8d4931a..5bc35ca 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
@@ -42,4 +42,7 @@
* [android.app.StatusBarManager.registerNearbyMediaDevicesProvider] for more information.
*/
fun areNearbyMediaDevicesEnabled() = featureFlags.isEnabled(Flags.MEDIA_NEARBY_DEVICES)
+
+ /** Check whether we show explicit indicator on UMO */
+ fun isExplicitIndicatorEnabled() = featureFlags.isEnabled(Flags.MEDIA_EXPLICIT_INDICATOR)
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogReceiver.kt b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogReceiver.kt
index 55fce59..760a42c 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogReceiver.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogReceiver.kt
@@ -36,10 +36,6 @@
) : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
when {
- TextUtils.equals(Intent.ACTION_SHOW_OUTPUT_SWITCHER, intent.action) -> {
- val packageName: String? = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME)
- launchMediaOutputDialogIfPossible(packageName)
- }
TextUtils.equals(
MediaOutputConstants.ACTION_LAUNCH_MEDIA_OUTPUT_DIALOG, intent.action) -> {
val packageName: String? =
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt
index 6c41caa..1d86343 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt
@@ -19,9 +19,11 @@
import android.app.Activity
import android.content.ComponentName
import android.content.Context
+import android.os.UserHandle
import com.android.launcher3.icons.IconFactory
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.media.MediaProjectionAppSelectorActivity
+import com.android.systemui.media.MediaProjectionAppSelectorActivity.Companion.EXTRA_HOST_APP_USER_HANDLE
import com.android.systemui.mediaprojection.appselector.data.ActivityTaskManagerThumbnailLoader
import com.android.systemui.mediaprojection.appselector.data.AppIconLoader
import com.android.systemui.mediaprojection.appselector.data.IconLoaderLibAppIconLoader
@@ -30,6 +32,8 @@
import com.android.systemui.mediaprojection.appselector.data.ShellRecentTaskListProvider
import com.android.systemui.mediaprojection.appselector.view.MediaProjectionRecentsViewController
import com.android.systemui.mediaprojection.appselector.view.TaskPreviewSizeProvider
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.shared.system.ActivityManagerWrapper
import com.android.systemui.statusbar.phone.ConfigurationControllerImpl
import com.android.systemui.statusbar.policy.ConfigurationController
import dagger.Binds
@@ -39,6 +43,7 @@
import dagger.Subcomponent
import dagger.multibindings.ClassKey
import dagger.multibindings.IntoMap
+import java.lang.IllegalArgumentException
import javax.inject.Qualifier
import javax.inject.Scope
import kotlinx.coroutines.CoroutineScope
@@ -46,6 +51,12 @@
@Qualifier @Retention(AnnotationRetention.BINARY) annotation class MediaProjectionAppSelector
+@Qualifier @Retention(AnnotationRetention.BINARY) annotation class HostUserHandle
+
+@Qualifier @Retention(AnnotationRetention.BINARY) annotation class PersonalProfile
+
+@Qualifier @Retention(AnnotationRetention.BINARY) annotation class WorkProfile
+
@Retention(AnnotationRetention.RUNTIME) @Scope annotation class MediaProjectionAppSelectorScope
@Module(subcomponents = [MediaProjectionAppSelectorComponent::class])
@@ -83,7 +94,7 @@
@MediaProjectionAppSelector
@MediaProjectionAppSelectorScope
fun provideAppSelectorComponentName(context: Context): ComponentName =
- ComponentName(context, MediaProjectionAppSelectorActivity::class.java)
+ ComponentName(context, MediaProjectionAppSelectorActivity::class.java)
@Provides
@MediaProjectionAppSelector
@@ -93,9 +104,32 @@
): ConfigurationController = ConfigurationControllerImpl(activity)
@Provides
- fun bindIconFactory(
- context: Context
- ): IconFactory = IconFactory.obtain(context)
+ @PersonalProfile
+ @MediaProjectionAppSelectorScope
+ fun personalUserHandle(activityManagerWrapper: ActivityManagerWrapper): UserHandle {
+ // Current foreground user is the 'personal' profile
+ return UserHandle.of(activityManagerWrapper.currentUserId)
+ }
+
+ @Provides
+ @WorkProfile
+ @MediaProjectionAppSelectorScope
+ fun workProfileUserHandle(userTracker: UserTracker): UserHandle? =
+ userTracker.userProfiles.find { it.isManagedProfile }?.userHandle
+
+ @Provides
+ @HostUserHandle
+ @MediaProjectionAppSelectorScope
+ fun hostUserHandle(activity: MediaProjectionAppSelectorActivity): UserHandle {
+ val extras =
+ activity.intent.extras
+ ?: error("MediaProjectionAppSelectorActivity should be launched with extras")
+ return extras.getParcelable(EXTRA_HOST_APP_USER_HANDLE)
+ ?: error("MediaProjectionAppSelectorActivity should be provided with " +
+ "$EXTRA_HOST_APP_USER_HANDLE extra")
+ }
+
+ @Provides fun bindIconFactory(context: Context): IconFactory = IconFactory.obtain(context)
@Provides
@MediaProjectionAppSelector
@@ -124,6 +158,8 @@
val controller: MediaProjectionAppSelectorController
val recentsViewController: MediaProjectionRecentsViewController
+ @get:HostUserHandle val hostUserHandle: UserHandle
+ @get:PersonalProfile val personalProfileUserHandle: UserHandle
@MediaProjectionAppSelector val configurationController: ConfigurationController
}
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorController.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorController.kt
index d744a40b..52c7ca3 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorController.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorController.kt
@@ -17,24 +17,36 @@
package com.android.systemui.mediaprojection.appselector
import android.content.ComponentName
+import android.os.UserHandle
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
import com.android.systemui.mediaprojection.appselector.data.RecentTask
import com.android.systemui.mediaprojection.appselector.data.RecentTaskListProvider
+import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
-import javax.inject.Inject
@MediaProjectionAppSelectorScope
-class MediaProjectionAppSelectorController @Inject constructor(
+class MediaProjectionAppSelectorController
+@Inject
+constructor(
private val recentTaskListProvider: RecentTaskListProvider,
private val view: MediaProjectionAppSelectorView,
+ private val flags: FeatureFlags,
+ @HostUserHandle private val hostUserHandle: UserHandle,
@MediaProjectionAppSelector private val scope: CoroutineScope,
@MediaProjectionAppSelector private val appSelectorComponentName: ComponentName
) {
fun init() {
scope.launch {
- val tasks = recentTaskListProvider.loadRecentTasks().sortTasks()
+ val recentTasks = recentTaskListProvider.loadRecentTasks()
+
+ val tasks = recentTasks
+ .filterDevicePolicyRestrictedTasks()
+ .sortedTasks()
+
view.bind(tasks)
}
}
@@ -43,9 +55,20 @@
scope.cancel()
}
- private fun List<RecentTask>.sortTasks(): List<RecentTask> =
- sortedBy {
- // Show normal tasks first and only then tasks with opened app selector
- it.topActivityComponent == appSelectorComponentName
+ /**
+ * Removes all recent tasks that are different from the profile of the host app to avoid any
+ * cross-profile sharing
+ */
+ private fun List<RecentTask>.filterDevicePolicyRestrictedTasks(): List<RecentTask> =
+ if (flags.isEnabled(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING_ENTERPRISE_POLICIES)) {
+ // TODO(b/263950746): filter tasks based on the enterprise policies
+ this
+ } else {
+ filter { UserHandle.of(it.userId) == hostUserHandle }
}
+
+ private fun List<RecentTask>.sortedTasks(): List<RecentTask> = sortedBy {
+ // Show normal tasks first and only then tasks with opened app selector
+ it.topActivityComponent == appSelectorComponentName
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTask.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTask.kt
index cd994b8..41e2286 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTask.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTask.kt
@@ -17,11 +17,12 @@
package com.android.systemui.mediaprojection.appselector.data
import android.annotation.ColorInt
+import android.annotation.UserIdInt
import android.content.ComponentName
data class RecentTask(
val taskId: Int,
- val userId: Int,
+ @UserIdInt val userId: Int,
val topActivityComponent: ComponentName?,
val baseIntentComponent: ComponentName?,
@ColorInt val colorBackground: Int?
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index 1f6270b..e0aa6a8 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -16,6 +16,7 @@
package com.android.systemui.navigationbar;
+import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED;
import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT;
import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SWITCHER_SHOWN;
import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN;
@@ -49,6 +50,7 @@
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SWITCHER_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
import static com.android.systemui.shared.system.QuickStepContract.isGesturalMode;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE;
import static com.android.systemui.statusbar.phone.BarTransitions.TransitionMode;
@@ -142,9 +144,10 @@
import com.android.systemui.shared.recents.utilities.Utilities;
import com.android.systemui.shared.rotation.RotationButton;
import com.android.systemui.shared.rotation.RotationButtonController;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.SysUiStatsLog;
+import com.android.systemui.shared.system.TaskStackChangeListener;
+import com.android.systemui.shared.system.TaskStackChangeListeners;
import com.android.systemui.statusbar.AutoHideUiElement;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.CommandQueue.Callbacks;
@@ -264,6 +267,7 @@
private final AutoHideController.Factory mAutoHideControllerFactory;
private final Optional<TelecomManager> mTelecomManagerOptional;
private final InputMethodManager mInputMethodManager;
+ private final TaskStackChangeListeners mTaskStackChangeListeners;
@VisibleForTesting
public int mDisplayId;
@@ -500,6 +504,18 @@
}
};
+ private boolean mScreenPinningActive = false;
+ private final TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() {
+ @Override
+ public void onLockTaskModeChanged(int mode) {
+ mScreenPinningActive = (mode == LOCK_TASK_MODE_PINNED);
+ mSysUiFlagsContainer.setFlag(SYSUI_STATE_SCREEN_PINNING, mScreenPinningActive)
+ .commitUpdate(mDisplayId);
+ mView.setInScreenPinning(mScreenPinningActive);
+ updateScreenPinningGestures();
+ }
+ };
+
@Inject
NavigationBar(
NavigationBarView navigationBarView,
@@ -541,7 +557,8 @@
EdgeBackGestureHandler edgeBackGestureHandler,
Optional<BackAnimation> backAnimation,
UserContextProvider userContextProvider,
- WakefulnessLifecycle wakefulnessLifecycle) {
+ WakefulnessLifecycle wakefulnessLifecycle,
+ TaskStackChangeListeners taskStackChangeListeners) {
super(navigationBarView);
mFrame = navigationBarFrame;
mContext = context;
@@ -580,6 +597,7 @@
mInputMethodManager = inputMethodManager;
mUserContextProvider = userContextProvider;
mWakefulnessLifecycle = wakefulnessLifecycle;
+ mTaskStackChangeListeners = taskStackChangeListeners;
mNavColorSampleMargin = getResources()
.getDimensionPixelSize(R.dimen.navigation_handle_sample_horizontal_margin);
@@ -692,6 +710,7 @@
mCommandQueue.recomputeDisableFlags(mDisplayId, false);
mNotificationShadeDepthController.addListener(mDepthListener);
+ mTaskStackChangeListeners.registerTaskStackListener(mTaskStackListener);
}
public void destroyView() {
@@ -705,6 +724,7 @@
mNotificationShadeDepthController.removeListener(mDepthListener);
mDeviceConfigProxy.removeOnPropertiesChangedListener(mOnPropertiesChangedListener);
+ mTaskStackChangeListeners.unregisterTaskStackListener(mTaskStackListener);
}
@Override
@@ -1005,11 +1025,15 @@
pw.println(" mTransientShown=" + mTransientShown);
pw.println(" mTransientShownFromGestureOnSystemBar="
+ mTransientShownFromGestureOnSystemBar);
+ pw.println(" mScreenPinningActive=" + mScreenPinningActive);
dumpBarTransitions(pw, "mNavigationBarView", getBarTransitions());
pw.println(" mOrientedHandleSamplingRegion: " + mOrientedHandleSamplingRegion);
mView.dump(pw);
mRegionSamplingHelper.dump(pw);
+ if (mAutoHideController != null) {
+ mAutoHideController.dump(pw);
+ }
}
// ----- CommandQueue Callbacks -----
@@ -1228,10 +1252,9 @@
private void updateScreenPinningGestures() {
// Change the cancel pin gesture to home and back if recents button is invisible
- boolean pinningActive = ActivityManagerWrapper.getInstance().isScreenPinningActive();
ButtonDispatcher backButton = mView.getBackButton();
ButtonDispatcher recentsButton = mView.getRecentsButton();
- if (pinningActive) {
+ if (mScreenPinningActive) {
boolean recentsVisible = mView.isRecentsButtonVisible();
backButton.setOnLongClickListener(recentsVisible
? this::onLongPressBackRecents
@@ -1242,8 +1265,8 @@
recentsButton.setOnLongClickListener(null);
}
// Note, this needs to be set after even if we're setting the listener to null
- backButton.setLongClickable(pinningActive);
- recentsButton.setLongClickable(pinningActive);
+ backButton.setLongClickable(mScreenPinningActive);
+ recentsButton.setLongClickable(mScreenPinningActive);
}
private void notifyNavigationBarScreenOn() {
@@ -1326,8 +1349,7 @@
@VisibleForTesting
boolean onHomeLongClick(View v) {
- if (!mView.isRecentsButtonVisible()
- && ActivityManagerWrapper.getInstance().isScreenPinningActive()) {
+ if (!mView.isRecentsButtonVisible() && mScreenPinningActive) {
return onLongPressBackHome(v);
}
if (shouldDisableNavbarGestures()) {
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
index 347707a..e64c188 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
@@ -57,6 +57,7 @@
import com.android.systemui.model.SysUiState;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.shared.system.QuickStepContract;
+import com.android.systemui.shared.system.TaskStackChangeListeners;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.CommandQueue.Callbacks;
import com.android.systemui.statusbar.phone.AutoHideController;
@@ -88,7 +89,6 @@
private FeatureFlags mFeatureFlags;
private final DisplayManager mDisplayManager;
private final TaskbarDelegate mTaskbarDelegate;
- private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
private int mNavMode;
@VisibleForTesting boolean mIsTablet;
@@ -112,10 +112,10 @@
NavBarHelper navBarHelper,
TaskbarDelegate taskbarDelegate,
NavigationBarComponent.Factory navigationBarComponentFactory,
- StatusBarKeyguardViewManager statusBarKeyguardViewManager,
DumpManager dumpManager,
AutoHideController autoHideController,
LightBarController lightBarController,
+ TaskStackChangeListeners taskStackChangeListeners,
Optional<Pip> pipOptional,
Optional<BackAnimation> backAnimation,
FeatureFlags featureFlags) {
@@ -129,11 +129,10 @@
mConfigChanges.applyNewConfig(mContext.getResources());
mNavMode = navigationModeController.addListener(this);
mTaskbarDelegate = taskbarDelegate;
- mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
mTaskbarDelegate.setDependencies(commandQueue, overviewProxyService,
navBarHelper, navigationModeController, sysUiFlagsContainer,
dumpManager, autoHideController, lightBarController, pipOptional,
- backAnimation.orElse(null));
+ backAnimation.orElse(null), taskStackChangeListeners);
mIsTablet = isTablet(mContext);
dumpManager.registerDumpable(this);
}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
index 403d276..88c4fd5 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
@@ -16,6 +16,7 @@
package com.android.systemui.navigationbar;
+import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED;
import static android.inputmethodservice.InputMethodService.canImeRenderGesturalNavButtons;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
@@ -80,6 +81,7 @@
import com.android.systemui.shared.rotation.RotationButtonController;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.QuickStepContract;
+import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.statusbar.phone.AutoHideController;
import com.android.systemui.statusbar.phone.CentralSurfaces;
import com.android.systemui.statusbar.phone.LightBarTransitionsController;
@@ -160,6 +162,7 @@
* fully locked mode we only show that unlocking is blocked.
*/
private ScreenPinningNotify mScreenPinningNotify;
+ private boolean mScreenPinningActive = false;
/**
* {@code true} if the IME can render the back button and the IME switcher button.
@@ -636,14 +639,13 @@
// When screen pinning, don't hide back and home when connected service or back and
// recents buttons when disconnected from launcher service in screen pinning mode,
// as they are used for exiting.
- final boolean pinningActive = ActivityManagerWrapper.getInstance().isScreenPinningActive();
if (mOverviewProxyEnabled) {
// Force disable recents when not in legacy mode
disableRecent |= !QuickStepContract.isLegacyMode(mNavBarMode);
- if (pinningActive && !QuickStepContract.isGesturalMode(mNavBarMode)) {
+ if (mScreenPinningActive && !QuickStepContract.isGesturalMode(mNavBarMode)) {
disableBack = disableHome = false;
}
- } else if (pinningActive) {
+ } else if (mScreenPinningActive) {
disableBack = disableRecent = false;
}
@@ -738,9 +740,7 @@
public void updateDisabledSystemUiStateFlags(SysUiState sysUiState) {
int displayId = mContext.getDisplayId();
- sysUiState.setFlag(SYSUI_STATE_SCREEN_PINNING,
- ActivityManagerWrapper.getInstance().isScreenPinningActive())
- .setFlag(SYSUI_STATE_OVERVIEW_DISABLED,
+ sysUiState.setFlag(SYSUI_STATE_OVERVIEW_DISABLED,
(mDisabledFlags & View.STATUS_BAR_DISABLE_RECENT) != 0)
.setFlag(SYSUI_STATE_HOME_DISABLED,
(mDisabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0)
@@ -749,6 +749,10 @@
.commitUpdate(displayId);
}
+ public void setInScreenPinning(boolean active) {
+ mScreenPinningActive = active;
+ }
+
private void updatePanelSystemUiStateFlags() {
if (SysUiState.DEBUG) {
Log.d(TAG, "Updating panel sysui state flags: panelView=" + mPanelView);
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
index f74756d..f3712e6 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
@@ -16,6 +16,7 @@
package com.android.systemui.navigationbar;
+import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED;
import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT;
import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SWITCHER_SHOWN;
import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
@@ -40,6 +41,7 @@
import android.app.StatusBarManager;
import android.app.StatusBarManager.WindowVisibleState;
+import android.content.ComponentName;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
@@ -68,6 +70,8 @@
import com.android.systemui.shared.recents.utilities.Utilities;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.QuickStepContract;
+import com.android.systemui.shared.system.TaskStackChangeListener;
+import com.android.systemui.shared.system.TaskStackChangeListeners;
import com.android.systemui.statusbar.AutoHideUiElement;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.AutoHideController;
@@ -101,6 +105,7 @@
private AutoHideController mAutoHideController;
private LightBarController mLightBarController;
private LightBarTransitionsController mLightBarTransitionsController;
+ private TaskStackChangeListeners mTaskStackChangeListeners;
private Optional<Pip> mPipOptional;
private int mDisplayId;
private int mNavigationIconHints;
@@ -127,6 +132,14 @@
private final DisplayManager mDisplayManager;
private Context mWindowContext;
private ScreenPinningNotify mScreenPinningNotify;
+ private final TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() {
+ @Override
+ public void onLockTaskModeChanged(int mode) {
+ mSysUiState.setFlag(SYSUI_STATE_SCREEN_PINNING, mode == LOCK_TASK_MODE_PINNED)
+ .commitUpdate(mDisplayId);
+ }
+ };
+
private int mNavigationMode = -1;
private final Consumer<Rect> mPipListener;
@@ -176,7 +189,8 @@
AutoHideController autoHideController,
LightBarController lightBarController,
Optional<Pip> pipOptional,
- BackAnimation backAnimation) {
+ BackAnimation backAnimation,
+ TaskStackChangeListeners taskStackChangeListeners) {
// TODO: adding this in the ctor results in a dagger dependency cycle :(
mCommandQueue = commandQueue;
mOverviewProxyService = overviewProxyService;
@@ -189,6 +203,7 @@
mPipOptional = pipOptional;
mBackAnimation = backAnimation;
mLightBarTransitionsController = createLightBarTransitionsController();
+ mTaskStackChangeListeners = taskStackChangeListeners;
}
// Separated into a method to keep setDependencies() clean/readable.
@@ -234,6 +249,7 @@
mPipOptional.ifPresent(this::addPipExclusionBoundsChangeListener);
mEdgeBackGestureHandler.setBackAnimation(mBackAnimation);
mEdgeBackGestureHandler.onConfigurationChanged(mContext.getResources().getConfiguration());
+ mTaskStackChangeListeners.registerTaskStackListener(mTaskStackListener);
mInitialized = true;
}
@@ -253,6 +269,7 @@
mLightBarTransitionsController.destroy();
mLightBarController.setNavigationBar(null);
mPipOptional.ifPresent(this::removePipExclusionBoundsChangeListener);
+ mTaskStackChangeListeners.unregisterTaskStackListener(mTaskStackListener);
mInitialized = false;
}
@@ -300,8 +317,6 @@
.setFlag(SYSUI_STATE_NAV_BAR_HIDDEN, !isWindowVisible())
.setFlag(SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY,
allowSystemGestureIgnoringBarVisibility())
- .setFlag(SYSUI_STATE_SCREEN_PINNING,
- ActivityManagerWrapper.getInstance().isScreenPinningActive())
.setFlag(SYSUI_STATE_IMMERSIVE_MODE, isImmersiveMode())
.commitUpdate(mDisplayId);
}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index e32c301..245a55d 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -279,7 +279,6 @@
@Override
public void triggerBack() {
// Notify FalsingManager that an intentional gesture has occurred.
- // TODO(b/186519446): use a different method than isFalseTouch
mFalsingManager.isFalseTouch(BACK_GESTURE);
// Only inject back keycodes when ahead-of-time back dispatching is disabled.
if (mBackAnimation == null) {
@@ -955,6 +954,10 @@
mThresholdCrossed = true;
// Capture inputs
mInputMonitor.pilferPointers();
+ if (mBackAnimation != null) {
+ // Notify FalsingManager that an intentional gesture has occurred.
+ mFalsingManager.isFalseTouch(BACK_GESTURE);
+ }
mInputEventReceiver.setBatchingEnabled(true);
} else {
logGesture(SysUiStatsLog.BACK_GESTURE__TYPE__INCOMPLETE_FAR_FROM_EDGE);
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
index 8356440..08d1857 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
@@ -104,4 +104,9 @@
PackageManager.DONT_KILL_APP,
)
}
+
+ companion object {
+ // TODO(b/254604589): Use final KeyEvent.KEYCODE_* instead.
+ const val NOTE_TASK_KEY_EVENT = 311
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInitializer.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInitializer.kt
index d14b7a7..d5f4a5a 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInitializer.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInitializer.kt
@@ -16,7 +16,6 @@
package com.android.systemui.notetask
-import android.view.KeyEvent
import androidx.annotation.VisibleForTesting
import com.android.systemui.statusbar.CommandQueue
import com.android.wm.shell.bubbles.Bubbles
@@ -37,7 +36,7 @@
val callbacks =
object : CommandQueue.Callbacks {
override fun handleSystemKey(keyCode: Int) {
- if (keyCode == KeyEvent.KEYCODE_VIDEO_APP_1) {
+ if (keyCode == NoteTaskController.NOTE_TASK_KEY_EVENT) {
noteTaskController.showNoteTask()
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskIntentResolver.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskIntentResolver.kt
index 98d6991..26e3f49 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskIntentResolver.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskIntentResolver.kt
@@ -21,12 +21,12 @@
import android.content.pm.ActivityInfo
import android.content.pm.PackageManager
import android.content.pm.PackageManager.ResolveInfoFlags
-import com.android.systemui.notetask.NoteTaskIntentResolver.Companion.NOTES_ACTION
+import com.android.systemui.notetask.NoteTaskIntentResolver.Companion.ACTION_CREATE_NOTE
import javax.inject.Inject
/**
- * Class responsible to query all apps and find one that can handle the [NOTES_ACTION]. If found, an
- * [Intent] ready for be launched will be returned. Otherwise, returns null.
+ * Class responsible to query all apps and find one that can handle the [ACTION_CREATE_NOTE]. If
+ * found, an [Intent] ready for be launched will be returned. Otherwise, returns null.
*
* TODO(b/248274123): should be revisited once the notes role is implemented.
*/
@@ -37,15 +37,16 @@
) {
fun resolveIntent(): Intent? {
- val intent = Intent(NOTES_ACTION)
+ val intent = Intent(ACTION_CREATE_NOTE)
val flags = ResolveInfoFlags.of(PackageManager.MATCH_DEFAULT_ONLY.toLong())
val infoList = packageManager.queryIntentActivities(intent, flags)
for (info in infoList) {
- val packageName = info.serviceInfo.applicationInfo.packageName ?: continue
+ val packageName = info.activityInfo.applicationInfo.packageName ?: continue
val activityName = resolveActivityNameForNotesAction(packageName) ?: continue
- return Intent(NOTES_ACTION)
+ return Intent(ACTION_CREATE_NOTE)
+ .setPackage(packageName)
.setComponent(ComponentName(packageName, activityName))
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
@@ -54,7 +55,7 @@
}
private fun resolveActivityNameForNotesAction(packageName: String): String? {
- val intent = Intent(NOTES_ACTION).setPackage(packageName)
+ val intent = Intent(ACTION_CREATE_NOTE).setPackage(packageName)
val flags = ResolveInfoFlags.of(PackageManager.MATCH_DEFAULT_ONLY.toLong())
val resolveInfo = packageManager.resolveActivity(intent, flags)
@@ -69,8 +70,8 @@
}
companion object {
- // TODO(b/254606432): Use Intent.ACTION_NOTES and Intent.ACTION_NOTES_LOCKED instead.
- const val NOTES_ACTION = "android.intent.action.NOTES"
+ // TODO(b/254606432): Use Intent.ACTION_CREATE_NOTE instead.
+ const val ACTION_CREATE_NOTE = "android.intent.action.CREATE_NOTE"
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivity.kt b/packages/SystemUI/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivity.kt
index 47fe676..f203e7a 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivity.kt
@@ -45,8 +45,8 @@
fun newIntent(context: Context): Intent {
return Intent(context, LaunchNoteTaskActivity::class.java).apply {
// Intent's action must be set in shortcuts, or an exception will be thrown.
- // TODO(b/254606432): Use Intent.ACTION_NOTES instead.
- action = NoteTaskIntentResolver.NOTES_ACTION
+ // TODO(b/254606432): Use Intent.ACTION_CREATE_NOTE instead.
+ action = NoteTaskIntentResolver.ACTION_CREATE_NOTE
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
index fba5f63..7f0f894 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
@@ -68,8 +68,10 @@
};
if (ComposeFacade.INSTANCE.isComposeAvailable()) {
+ Log.d(TAG, "Using the Compose implementation of the PeopleSpaceActivity");
ComposeFacade.INSTANCE.setPeopleSpaceActivityContent(this, viewModel, onResult);
} else {
+ Log.d(TAG, "Using the View implementation of the PeopleSpaceActivity");
ViewGroup view = PeopleViewBinder.create(this);
PeopleViewBinder.bind(view, viewModel, /* lifecycleOwner= */ this, onResult);
setContentView(view);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 5ef7126..b673f0e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -48,6 +48,7 @@
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
import com.android.systemui.animation.ShadeInterpolation;
+import com.android.systemui.compose.ComposeFacade;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.media.controls.ui.MediaHost;
@@ -227,9 +228,7 @@
mQSFooterActionsViewModel = mFooterActionsViewModelFactory.create(/* lifecycleOwner */
this);
- LinearLayout footerActionsView = view.findViewById(R.id.qs_footer_actions);
- FooterActionsViewBinder.bind(footerActionsView, mQSFooterActionsViewModel,
- mListeningAndVisibilityLifecycleOwner);
+ bindFooterActionsView(view);
mFooterActionsController.init();
mQSPanelScrollView = view.findViewById(R.id.expanded_qs_scroll_view);
@@ -290,6 +289,33 @@
});
}
+ private void bindFooterActionsView(View root) {
+ LinearLayout footerActionsView = root.findViewById(R.id.qs_footer_actions);
+
+ if (!ComposeFacade.INSTANCE.isComposeAvailable()) {
+ Log.d(TAG, "Binding the View implementation of the QS footer actions");
+ FooterActionsViewBinder.bind(footerActionsView, mQSFooterActionsViewModel,
+ mListeningAndVisibilityLifecycleOwner);
+ return;
+ }
+
+ // Compose is available, so let's use the Compose implementation of the footer actions.
+ Log.d(TAG, "Binding the Compose implementation of the QS footer actions");
+ View composeView = ComposeFacade.INSTANCE.createFooterActionsView(root.getContext(),
+ mQSFooterActionsViewModel, mListeningAndVisibilityLifecycleOwner);
+
+ // The id R.id.qs_footer_actions is used by QSContainerImpl to set the horizontal margin
+ // to all views except for qs_footer_actions, so we set it to the Compose view.
+ composeView.setId(R.id.qs_footer_actions);
+
+ // Replace the View by the Compose provided one.
+ ViewGroup parent = (ViewGroup) footerActionsView.getParent();
+ ViewGroup.LayoutParams layoutParams = footerActionsView.getLayoutParams();
+ int index = parent.indexOfChild(footerActionsView);
+ parent.removeViewAt(index);
+ parent.addView(composeView, index, layoutParams);
+ }
+
@Override
public void setScrollListener(ScrollListener listener) {
mScrollListener = listener;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSHost.java
index 7cf63f6..1da30ad 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSHost.java
@@ -36,7 +36,6 @@
void removeCallback(Callback callback);
void removeTile(String tileSpec);
void removeTiles(Collection<String> specs);
- void unmarkTileAsAutoAdded(String tileSpec);
int indexOf(String tileSpec);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
index cad296b..100853c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
@@ -427,11 +427,6 @@
mMainExecutor.execute(() -> changeTileSpecs(tileSpecs -> tileSpecs.removeAll(specs)));
}
- @Override
- public void unmarkTileAsAutoAdded(String spec) {
- if (mAutoTiles != null) mAutoTiles.unmarkTileAsAutoAdded(spec);
- }
-
/**
* Add a tile to the end
*
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
index 3d48fd1..84a18d8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
@@ -132,7 +132,7 @@
final String slot = tile.getComponent().getClassName();
// TileServices doesn't know how to add more than 1 icon per slot, so remove all
mMainHandler.post(() -> mHost.getIconController()
- .removeAllIconsForSlot(slot));
+ .removeAllIconsForExternalSlot(slot));
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/binder/FooterActionsViewBinder.kt b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/binder/FooterActionsViewBinder.kt
index 30f8124..1921586 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/binder/FooterActionsViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/binder/FooterActionsViewBinder.kt
@@ -219,9 +219,9 @@
// Small button with the number only.
foregroundServicesWithTextView.isVisible = false
- foregroundServicesWithNumberView.visibility = View.VISIBLE
+ foregroundServicesWithNumberView.isVisible = true
foregroundServicesWithNumberView.setOnClickListener {
- foregroundServices.onClick(Expandable.fromView(foregroundServicesWithTextView))
+ foregroundServices.onClick(Expandable.fromView(foregroundServicesWithNumberView))
}
foregroundServicesWithNumberHolder.number.text = foregroundServicesCount.toString()
foregroundServicesWithNumberHolder.number.contentDescription = foregroundServices.text
diff --git a/packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt b/packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt
index 9f376ae..d32ef32 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt
@@ -49,109 +49,135 @@
}
fun logTileAdded(tileSpec: String) {
- log(DEBUG, {
- str1 = tileSpec
- }, {
- "[$str1] Tile added"
- })
+ buffer.log(TAG, DEBUG, { str1 = tileSpec }, { "[$str1] Tile added" })
}
fun logTileDestroyed(tileSpec: String, reason: String) {
- log(DEBUG, {
- str1 = tileSpec
- str2 = reason
- }, {
- "[$str1] Tile destroyed. Reason: $str2"
- })
+ buffer.log(
+ TAG,
+ DEBUG,
+ {
+ str1 = tileSpec
+ str2 = reason
+ },
+ { "[$str1] Tile destroyed. Reason: $str2" }
+ )
}
fun logTileChangeListening(tileSpec: String, listening: Boolean) {
- log(VERBOSE, {
- bool1 = listening
- str1 = tileSpec
- }, {
- "[$str1] Tile listening=$bool1"
- })
+ buffer.log(
+ TAG,
+ VERBOSE,
+ {
+ bool1 = listening
+ str1 = tileSpec
+ },
+ { "[$str1] Tile listening=$bool1" }
+ )
}
fun logAllTilesChangeListening(listening: Boolean, containerName: String, allSpecs: String) {
- log(DEBUG, {
- bool1 = listening
- str1 = containerName
- str2 = allSpecs
- }, {
- "Tiles listening=$bool1 in $str1. $str2"
- })
+ buffer.log(
+ TAG,
+ DEBUG,
+ {
+ bool1 = listening
+ str1 = containerName
+ str2 = allSpecs
+ },
+ { "Tiles listening=$bool1 in $str1. $str2" }
+ )
}
fun logTileClick(tileSpec: String, statusBarState: Int, state: Int, eventId: Int) {
- log(DEBUG, {
- str1 = tileSpec
- int1 = eventId
- str2 = StatusBarState.toString(statusBarState)
- str3 = toStateString(state)
- }, {
- "[$str1][$int1] Tile clicked. StatusBarState=$str2. TileState=$str3"
- })
+ buffer.log(
+ TAG,
+ DEBUG,
+ {
+ str1 = tileSpec
+ int1 = eventId
+ str2 = StatusBarState.toString(statusBarState)
+ str3 = toStateString(state)
+ },
+ { "[$str1][$int1] Tile clicked. StatusBarState=$str2. TileState=$str3" }
+ )
}
fun logHandleClick(tileSpec: String, eventId: Int) {
- log(DEBUG, {
- str1 = tileSpec
- int1 = eventId
- }, {
- "[$str1][$int1] Tile handling click."
- })
+ buffer.log(
+ TAG,
+ DEBUG,
+ {
+ str1 = tileSpec
+ int1 = eventId
+ },
+ { "[$str1][$int1] Tile handling click." }
+ )
}
fun logTileSecondaryClick(tileSpec: String, statusBarState: Int, state: Int, eventId: Int) {
- log(DEBUG, {
- str1 = tileSpec
- int1 = eventId
- str2 = StatusBarState.toString(statusBarState)
- str3 = toStateString(state)
- }, {
- "[$str1][$int1] Tile secondary clicked. StatusBarState=$str2. TileState=$str3"
- })
+ buffer.log(
+ TAG,
+ DEBUG,
+ {
+ str1 = tileSpec
+ int1 = eventId
+ str2 = StatusBarState.toString(statusBarState)
+ str3 = toStateString(state)
+ },
+ { "[$str1][$int1] Tile secondary clicked. StatusBarState=$str2. TileState=$str3" }
+ )
}
fun logHandleSecondaryClick(tileSpec: String, eventId: Int) {
- log(DEBUG, {
- str1 = tileSpec
- int1 = eventId
- }, {
- "[$str1][$int1] Tile handling secondary click."
- })
+ buffer.log(
+ TAG,
+ DEBUG,
+ {
+ str1 = tileSpec
+ int1 = eventId
+ },
+ { "[$str1][$int1] Tile handling secondary click." }
+ )
}
fun logTileLongClick(tileSpec: String, statusBarState: Int, state: Int, eventId: Int) {
- log(DEBUG, {
- str1 = tileSpec
- int1 = eventId
- str2 = StatusBarState.toString(statusBarState)
- str3 = toStateString(state)
- }, {
- "[$str1][$int1] Tile long clicked. StatusBarState=$str2. TileState=$str3"
- })
+ buffer.log(
+ TAG,
+ DEBUG,
+ {
+ str1 = tileSpec
+ int1 = eventId
+ str2 = StatusBarState.toString(statusBarState)
+ str3 = toStateString(state)
+ },
+ { "[$str1][$int1] Tile long clicked. StatusBarState=$str2. TileState=$str3" }
+ )
}
fun logHandleLongClick(tileSpec: String, eventId: Int) {
- log(DEBUG, {
- str1 = tileSpec
- int1 = eventId
- }, {
- "[$str1][$int1] Tile handling long click."
- })
+ buffer.log(
+ TAG,
+ DEBUG,
+ {
+ str1 = tileSpec
+ int1 = eventId
+ },
+ { "[$str1][$int1] Tile handling long click." }
+ )
}
fun logInternetTileUpdate(tileSpec: String, lastType: Int, callback: String) {
- log(VERBOSE, {
- str1 = tileSpec
- int1 = lastType
- str2 = callback
- }, {
- "[$str1] mLastTileState=$int1, Callback=$str2."
- })
+ buffer.log(
+ TAG,
+ VERBOSE,
+ {
+ str1 = tileSpec
+ int1 = lastType
+ str2 = callback
+ },
+ { "[$str1] mLastTileState=$int1, Callback=$str2." }
+ )
}
// TODO(b/250618218): Remove this method once we know the root cause of b/250618218.
@@ -167,58 +193,75 @@
if (tileSpec != "internet") {
return
}
- log(VERBOSE, {
- str1 = tileSpec
- int1 = state
- bool1 = disabledByPolicy
- int2 = color
- }, {
- "[$str1] state=$int1, disabledByPolicy=$bool1, color=$int2."
- })
+ buffer.log(
+ TAG,
+ VERBOSE,
+ {
+ str1 = tileSpec
+ int1 = state
+ bool1 = disabledByPolicy
+ int2 = color
+ },
+ { "[$str1] state=$int1, disabledByPolicy=$bool1, color=$int2." }
+ )
}
fun logTileUpdated(tileSpec: String, state: QSTile.State) {
- log(VERBOSE, {
- str1 = tileSpec
- str2 = state.label?.toString()
- str3 = state.icon?.toString()
- int1 = state.state
- if (state is QSTile.SignalState) {
- bool1 = true
- bool2 = state.activityIn
- bool3 = state.activityOut
+ buffer.log(
+ TAG,
+ VERBOSE,
+ {
+ str1 = tileSpec
+ str2 = state.label?.toString()
+ str3 = state.icon?.toString()
+ int1 = state.state
+ if (state is QSTile.SignalState) {
+ bool1 = true
+ bool2 = state.activityIn
+ bool3 = state.activityOut
+ }
+ },
+ {
+ "[$str1] Tile updated. Label=$str2. State=$int1. Icon=$str3." +
+ if (bool1) " Activity in/out=$bool2/$bool3" else ""
}
- }, {
- "[$str1] Tile updated. Label=$str2. State=$int1. Icon=$str3." +
- if (bool1) " Activity in/out=$bool2/$bool3" else ""
- })
+ )
}
fun logPanelExpanded(expanded: Boolean, containerName: String) {
- log(DEBUG, {
- str1 = containerName
- bool1 = expanded
- }, {
- "$str1 expanded=$bool1"
- })
+ buffer.log(
+ TAG,
+ DEBUG,
+ {
+ str1 = containerName
+ bool1 = expanded
+ },
+ { "$str1 expanded=$bool1" }
+ )
}
fun logOnViewAttached(orientation: Int, containerName: String) {
- log(DEBUG, {
- str1 = containerName
- int1 = orientation
- }, {
- "onViewAttached: $str1 orientation $int1"
- })
+ buffer.log(
+ TAG,
+ DEBUG,
+ {
+ str1 = containerName
+ int1 = orientation
+ },
+ { "onViewAttached: $str1 orientation $int1" }
+ )
}
fun logOnViewDetached(orientation: Int, containerName: String) {
- log(DEBUG, {
- str1 = containerName
- int1 = orientation
- }, {
- "onViewDetached: $str1 orientation $int1"
- })
+ buffer.log(
+ TAG,
+ DEBUG,
+ {
+ str1 = containerName
+ int1 = orientation
+ },
+ { "onViewDetached: $str1 orientation $int1" }
+ )
}
fun logOnConfigurationChanged(
@@ -226,13 +269,16 @@
newOrientation: Int,
containerName: String
) {
- log(DEBUG, {
- str1 = containerName
- int1 = lastOrientation
- int2 = newOrientation
- }, {
- "configuration change: $str1 orientation was $int1, now $int2"
- })
+ buffer.log(
+ TAG,
+ DEBUG,
+ {
+ str1 = containerName
+ int1 = lastOrientation
+ int2 = newOrientation
+ },
+ { "configuration change: $str1 orientation was $int1, now $int2" }
+ )
}
fun logSwitchTileLayout(
@@ -241,32 +287,41 @@
force: Boolean,
containerName: String
) {
- log(DEBUG, {
- str1 = containerName
- bool1 = after
- bool2 = before
- bool3 = force
- }, {
- "change tile layout: $str1 horizontal=$bool1 (was $bool2), force? $bool3"
- })
+ buffer.log(
+ TAG,
+ DEBUG,
+ {
+ str1 = containerName
+ bool1 = after
+ bool2 = before
+ bool3 = force
+ },
+ { "change tile layout: $str1 horizontal=$bool1 (was $bool2), force? $bool3" }
+ )
}
fun logTileDistributionInProgress(tilesPerPageCount: Int, totalTilesCount: Int) {
- log(DEBUG, {
- int1 = tilesPerPageCount
- int2 = totalTilesCount
- }, {
- "Distributing tiles: [tilesPerPageCount=$int1] [totalTilesCount=$int2]"
- })
+ buffer.log(
+ TAG,
+ DEBUG,
+ {
+ int1 = tilesPerPageCount
+ int2 = totalTilesCount
+ },
+ { "Distributing tiles: [tilesPerPageCount=$int1] [totalTilesCount=$int2]" }
+ )
}
fun logTileDistributed(tileName: String, pageIndex: Int) {
- log(DEBUG, {
- str1 = tileName
- int1 = pageIndex
- }, {
- "Adding $str1 to page number $int1"
- })
+ buffer.log(
+ TAG,
+ DEBUG,
+ {
+ str1 = tileName
+ int1 = pageIndex
+ },
+ { "Adding $str1 to page number $int1" }
+ )
}
private fun toStateString(state: Int): String {
@@ -277,12 +332,4 @@
else -> "wrong state"
}
}
-
- private inline fun log(
- logLevel: LogLevel,
- initializer: LogMessage.() -> Unit,
- noinline printer: LogMessage.() -> String
- ) {
- buffer.log(TAG, logLevel, initializer, printer)
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
index a92c7e3..24a4f60b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
@@ -33,7 +33,6 @@
import com.android.systemui.qs.tiles.BluetoothTile;
import com.android.systemui.qs.tiles.CameraToggleTile;
import com.android.systemui.qs.tiles.CastTile;
-import com.android.systemui.qs.tiles.CellularTile;
import com.android.systemui.qs.tiles.ColorCorrectionTile;
import com.android.systemui.qs.tiles.ColorInversionTile;
import com.android.systemui.qs.tiles.DataSaverTile;
@@ -54,7 +53,6 @@
import com.android.systemui.qs.tiles.RotationLockTile;
import com.android.systemui.qs.tiles.ScreenRecordTile;
import com.android.systemui.qs.tiles.UiModeNightTile;
-import com.android.systemui.qs.tiles.WifiTile;
import com.android.systemui.qs.tiles.WorkModeTile;
import com.android.systemui.util.leak.GarbageMonitor;
@@ -68,10 +66,8 @@
private static final String TAG = "QSFactory";
- private final Provider<WifiTile> mWifiTileProvider;
private final Provider<InternetTile> mInternetTileProvider;
private final Provider<BluetoothTile> mBluetoothTileProvider;
- private final Provider<CellularTile> mCellularTileProvider;
private final Provider<DndTile> mDndTileProvider;
private final Provider<ColorCorrectionTile> mColorCorrectionTileProvider;
private final Provider<ColorInversionTile> mColorInversionTileProvider;
@@ -106,10 +102,8 @@
public QSFactoryImpl(
Lazy<QSHost> qsHostLazy,
Provider<CustomTile.Builder> customTileBuilderProvider,
- Provider<WifiTile> wifiTileProvider,
Provider<InternetTile> internetTileProvider,
Provider<BluetoothTile> bluetoothTileProvider,
- Provider<CellularTile> cellularTileProvider,
Provider<DndTile> dndTileProvider,
Provider<ColorInversionTile> colorInversionTileProvider,
Provider<AirplaneModeTile> airplaneModeTileProvider,
@@ -139,10 +133,8 @@
mQsHostLazy = qsHostLazy;
mCustomTileBuilderProvider = customTileBuilderProvider;
- mWifiTileProvider = wifiTileProvider;
mInternetTileProvider = internetTileProvider;
mBluetoothTileProvider = bluetoothTileProvider;
- mCellularTileProvider = cellularTileProvider;
mDndTileProvider = dndTileProvider;
mColorInversionTileProvider = colorInversionTileProvider;
mAirplaneModeTileProvider = airplaneModeTileProvider;
@@ -186,14 +178,10 @@
protected QSTileImpl createTileInternal(String tileSpec) {
// Stock tiles.
switch (tileSpec) {
- case "wifi":
- return mWifiTileProvider.get();
case "internet":
return mInternetTileProvider.get();
case "bt":
return mBluetoothTileProvider.get();
- case "cell":
- return mCellularTileProvider.get();
case "dnd":
return mDndTileProvider.get();
case "inversion":
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
index b355d4b..29d7fb0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
@@ -145,7 +145,6 @@
private val launchableViewDelegate = LaunchableViewDelegate(
this,
superSetVisibility = { super.setVisibility(it) },
- superSetTransitionVisibility = { super.setTransitionVisibility(it) },
)
private var lastDisabledByPolicy = false
@@ -362,10 +361,6 @@
launchableViewDelegate.setVisibility(visibility)
}
- override fun setTransitionVisibility(visibility: Int) {
- launchableViewDelegate.setTransitionVisibility(visibility)
- }
-
// Accessibility
override fun onInitializeAccessibilityEvent(event: AccessibilityEvent) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
deleted file mode 100644
index 04a25fc..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs.tiles;
-
-import static com.android.systemui.Prefs.Key.QS_HAS_TURNED_OFF_MOBILE_DATA;
-
-import android.annotation.NonNull;
-import android.app.AlertDialog;
-import android.app.AlertDialog.Builder;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Resources;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.service.quicksettings.Tile;
-import android.telephony.SubscriptionManager;
-import android.text.Html;
-import android.text.TextUtils;
-import android.view.View;
-import android.view.WindowManager.LayoutParams;
-import android.widget.Switch;
-
-import androidx.annotation.Nullable;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settingslib.net.DataUsageController;
-import com.android.systemui.Prefs;
-import com.android.systemui.R;
-import com.android.systemui.dagger.qualifiers.Background;
-import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.plugins.FalsingManager;
-import com.android.systemui.plugins.qs.QSIconView;
-import com.android.systemui.plugins.qs.QSTile.SignalState;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.qs.QSHost;
-import com.android.systemui.qs.SignalTileView;
-import com.android.systemui.qs.logging.QSLogger;
-import com.android.systemui.qs.tileimpl.QSTileImpl;
-import com.android.systemui.statusbar.connectivity.IconState;
-import com.android.systemui.statusbar.connectivity.MobileDataIndicators;
-import com.android.systemui.statusbar.connectivity.NetworkController;
-import com.android.systemui.statusbar.connectivity.SignalCallback;
-import com.android.systemui.statusbar.phone.SystemUIDialog;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
-
-import javax.inject.Inject;
-
-/** Quick settings tile: Cellular **/
-public class CellularTile extends QSTileImpl<SignalState> {
- private static final String ENABLE_SETTINGS_DATA_PLAN = "enable.settings.data.plan";
-
- private final NetworkController mController;
- private final DataUsageController mDataController;
- private final KeyguardStateController mKeyguard;
- private final CellSignalCallback mSignalCallback = new CellSignalCallback();
-
- @Inject
- public CellularTile(
- QSHost host,
- @Background Looper backgroundLooper,
- @Main Handler mainHandler,
- FalsingManager falsingManager,
- MetricsLogger metricsLogger,
- StatusBarStateController statusBarStateController,
- ActivityStarter activityStarter,
- QSLogger qsLogger,
- NetworkController networkController,
- KeyguardStateController keyguardStateController
-
- ) {
- super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger,
- statusBarStateController, activityStarter, qsLogger);
- mController = networkController;
- mKeyguard = keyguardStateController;
- mDataController = mController.getMobileDataController();
- mController.observe(getLifecycle(), mSignalCallback);
- }
-
- @Override
- public SignalState newTileState() {
- return new SignalState();
- }
-
- @Override
- public QSIconView createTileView(Context context) {
- return new SignalTileView(context);
- }
-
- @Override
- public Intent getLongClickIntent() {
- if (getState().state == Tile.STATE_UNAVAILABLE) {
- return new Intent(Settings.ACTION_WIRELESS_SETTINGS);
- }
- return getCellularSettingIntent();
- }
-
- @Override
- protected void handleClick(@Nullable View view) {
- if (getState().state == Tile.STATE_UNAVAILABLE) {
- return;
- }
- if (mDataController.isMobileDataEnabled()) {
- maybeShowDisableDialog();
- } else {
- mDataController.setMobileDataEnabled(true);
- }
- }
-
- private void maybeShowDisableDialog() {
- if (Prefs.getBoolean(mContext, QS_HAS_TURNED_OFF_MOBILE_DATA, false)) {
- // Directly turn off mobile data if the user has seen the dialog before.
- mDataController.setMobileDataEnabled(false);
- return;
- }
- String carrierName = mController.getMobileDataNetworkName();
- boolean isInService = mController.isMobileDataNetworkInService();
- if (TextUtils.isEmpty(carrierName) || !isInService) {
- carrierName = mContext.getString(R.string.mobile_data_disable_message_default_carrier);
- }
- AlertDialog dialog = new Builder(mContext)
- .setTitle(R.string.mobile_data_disable_title)
- .setMessage(mContext.getString(R.string.mobile_data_disable_message, carrierName))
- .setNegativeButton(android.R.string.cancel, null)
- .setPositiveButton(
- com.android.internal.R.string.alert_windows_notification_turn_off_action,
- (d, w) -> {
- mDataController.setMobileDataEnabled(false);
- Prefs.putBoolean(mContext, QS_HAS_TURNED_OFF_MOBILE_DATA, true);
- })
- .create();
- dialog.getWindow().setType(LayoutParams.TYPE_KEYGUARD_DIALOG);
- SystemUIDialog.setShowForAllUsers(dialog, true);
- SystemUIDialog.registerDismissListener(dialog);
- SystemUIDialog.setWindowOnTop(dialog, mKeyguard.isShowing());
- dialog.show();
- }
-
- @Override
- protected void handleSecondaryClick(@Nullable View view) {
- handleLongClick(view);
- }
-
- @Override
- public CharSequence getTileLabel() {
- return mContext.getString(R.string.quick_settings_cellular_detail_title);
- }
-
- @Override
- protected void handleUpdateState(SignalState state, Object arg) {
- CallbackInfo cb = (CallbackInfo) arg;
- if (cb == null) {
- cb = mSignalCallback.mInfo;
- }
-
- final Resources r = mContext.getResources();
- state.label = r.getString(R.string.mobile_data);
- boolean mobileDataEnabled = mDataController.isMobileDataSupported()
- && mDataController.isMobileDataEnabled();
- state.value = mobileDataEnabled;
- state.activityIn = mobileDataEnabled && cb.activityIn;
- state.activityOut = mobileDataEnabled && cb.activityOut;
- state.expandedAccessibilityClassName = Switch.class.getName();
- if (cb.noSim) {
- state.icon = ResourceIcon.get(R.drawable.ic_qs_no_sim);
- } else {
- state.icon = ResourceIcon.get(R.drawable.ic_swap_vert);
- }
-
- if (cb.noSim) {
- state.state = Tile.STATE_UNAVAILABLE;
- state.secondaryLabel = r.getString(R.string.keyguard_missing_sim_message_short);
- } else if (cb.airplaneModeEnabled) {
- state.state = Tile.STATE_UNAVAILABLE;
- state.secondaryLabel = r.getString(R.string.status_bar_airplane);
- } else if (mobileDataEnabled) {
- state.state = Tile.STATE_ACTIVE;
- state.secondaryLabel = appendMobileDataType(
- // Only show carrier name if there are more than 1 subscription
- cb.multipleSubs ? cb.dataSubscriptionName : "",
- getMobileDataContentName(cb));
- } else {
- state.state = Tile.STATE_INACTIVE;
- state.secondaryLabel = r.getString(R.string.cell_data_off);
- }
-
- state.contentDescription = state.label;
- if (state.state == Tile.STATE_INACTIVE) {
- // This information is appended later by converting the Tile.STATE_INACTIVE state.
- state.stateDescription = "";
- } else {
- state.stateDescription = state.secondaryLabel;
- }
- }
-
- private CharSequence appendMobileDataType(CharSequence current, CharSequence dataType) {
- if (TextUtils.isEmpty(dataType)) {
- return Html.fromHtml(current.toString(), 0);
- }
- if (TextUtils.isEmpty(current)) {
- return Html.fromHtml(dataType.toString(), 0);
- }
- String concat = mContext.getString(R.string.mobile_carrier_text_format, current, dataType);
- return Html.fromHtml(concat, 0);
- }
-
- private CharSequence getMobileDataContentName(CallbackInfo cb) {
- if (cb.roaming && !TextUtils.isEmpty(cb.dataContentDescription)) {
- String roaming = mContext.getString(R.string.data_connection_roaming);
- String dataDescription = cb.dataContentDescription.toString();
- return mContext.getString(R.string.mobile_data_text_format, roaming, dataDescription);
- }
- if (cb.roaming) {
- return mContext.getString(R.string.data_connection_roaming);
- }
- return cb.dataContentDescription;
- }
-
- @Override
- public int getMetricsCategory() {
- return MetricsEvent.QS_CELLULAR;
- }
-
- @Override
- public boolean isAvailable() {
- return mController.hasMobileDataFeature()
- && mHost.getUserContext().getUserId() == UserHandle.USER_SYSTEM;
- }
-
- private static final class CallbackInfo {
- boolean airplaneModeEnabled;
- @Nullable
- CharSequence dataSubscriptionName;
- @Nullable
- CharSequence dataContentDescription;
- boolean activityIn;
- boolean activityOut;
- boolean noSim;
- boolean roaming;
- boolean multipleSubs;
- }
-
- private final class CellSignalCallback implements SignalCallback {
- private final CallbackInfo mInfo = new CallbackInfo();
-
- @Override
- public void setMobileDataIndicators(@NonNull MobileDataIndicators indicators) {
- if (indicators.qsIcon == null) {
- // Not data sim, don't display.
- return;
- }
- mInfo.dataSubscriptionName = mController.getMobileDataNetworkName();
- mInfo.dataContentDescription = indicators.qsDescription != null
- ? indicators.typeContentDescriptionHtml : null;
- mInfo.activityIn = indicators.activityIn;
- mInfo.activityOut = indicators.activityOut;
- mInfo.roaming = indicators.roaming;
- mInfo.multipleSubs = mController.getNumberSubscriptions() > 1;
- refreshState(mInfo);
- }
-
- @Override
- public void setNoSims(boolean show, boolean simDetected) {
- mInfo.noSim = show;
- refreshState(mInfo);
- }
-
- @Override
- public void setIsAirplaneMode(@NonNull IconState icon) {
- mInfo.airplaneModeEnabled = icon.visible;
- refreshState(mInfo);
- }
- }
-
- static Intent getCellularSettingIntent() {
- Intent intent = new Intent(Settings.ACTION_NETWORK_OPERATOR_SETTINGS);
- int dataSub = SubscriptionManager.getDefaultDataSubscriptionId();
- if (dataSub != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
- intent.putExtra(Settings.EXTRA_SUB_ID,
- SubscriptionManager.getDefaultDataSubscriptionId());
- }
- return intent;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
deleted file mode 100644
index b2be56cc..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs.tiles;
-
-import android.annotation.NonNull;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.os.Handler;
-import android.os.Looper;
-import android.provider.Settings;
-import android.service.quicksettings.Tile;
-import android.text.TextUtils;
-import android.util.Log;
-import android.view.View;
-import android.widget.Switch;
-
-import androidx.annotation.Nullable;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.R;
-import com.android.systemui.dagger.qualifiers.Background;
-import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.plugins.FalsingManager;
-import com.android.systemui.plugins.qs.QSIconView;
-import com.android.systemui.plugins.qs.QSTile;
-import com.android.systemui.plugins.qs.QSTile.SignalState;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.qs.AlphaControlledSignalTileView;
-import com.android.systemui.qs.QSHost;
-import com.android.systemui.qs.logging.QSLogger;
-import com.android.systemui.qs.tileimpl.QSIconViewImpl;
-import com.android.systemui.qs.tileimpl.QSTileImpl;
-import com.android.systemui.statusbar.connectivity.AccessPointController;
-import com.android.systemui.statusbar.connectivity.NetworkController;
-import com.android.systemui.statusbar.connectivity.SignalCallback;
-import com.android.systemui.statusbar.connectivity.WifiIcons;
-import com.android.systemui.statusbar.connectivity.WifiIndicators;
-
-import javax.inject.Inject;
-
-/** Quick settings tile: Wifi **/
-public class WifiTile extends QSTileImpl<SignalState> {
- private static final Intent WIFI_SETTINGS = new Intent(Settings.ACTION_WIFI_SETTINGS);
-
- protected final NetworkController mController;
- private final AccessPointController mWifiController;
- private final QSTile.SignalState mStateBeforeClick = newTileState();
-
- protected final WifiSignalCallback mSignalCallback = new WifiSignalCallback();
- private boolean mExpectDisabled;
-
- @Inject
- public WifiTile(
- QSHost host,
- @Background Looper backgroundLooper,
- @Main Handler mainHandler,
- FalsingManager falsingManager,
- MetricsLogger metricsLogger,
- StatusBarStateController statusBarStateController,
- ActivityStarter activityStarter,
- QSLogger qsLogger,
- NetworkController networkController,
- AccessPointController accessPointController
- ) {
- super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger,
- statusBarStateController, activityStarter, qsLogger);
- mController = networkController;
- mWifiController = accessPointController;
- mController.observe(getLifecycle(), mSignalCallback);
- mStateBeforeClick.spec = "wifi";
- }
-
- @Override
- public SignalState newTileState() {
- return new SignalState();
- }
-
- @Override
- public QSIconView createTileView(Context context) {
- return new AlphaControlledSignalTileView(context);
- }
-
- @Override
- public Intent getLongClickIntent() {
- return WIFI_SETTINGS;
- }
-
- @Override
- protected void handleClick(@Nullable View view) {
- // Secondary clicks are header clicks, just toggle.
- mState.copyTo(mStateBeforeClick);
- boolean wifiEnabled = mState.value;
- // Immediately enter transient state when turning on wifi.
- refreshState(wifiEnabled ? null : ARG_SHOW_TRANSIENT_ENABLING);
- mController.setWifiEnabled(!wifiEnabled);
- mExpectDisabled = wifiEnabled;
- if (mExpectDisabled) {
- mHandler.postDelayed(() -> {
- if (mExpectDisabled) {
- mExpectDisabled = false;
- refreshState();
- }
- }, QSIconViewImpl.QS_ANIM_LENGTH);
- }
- }
-
- @Override
- protected void handleSecondaryClick(@Nullable View view) {
- if (!mWifiController.canConfigWifi()) {
- mActivityStarter.postStartActivityDismissingKeyguard(
- new Intent(Settings.ACTION_WIFI_SETTINGS), 0);
- return;
- }
- if (!mState.value) {
- mController.setWifiEnabled(true);
- }
- }
-
- @Override
- public CharSequence getTileLabel() {
- return mContext.getString(R.string.quick_settings_wifi_label);
- }
-
- @Override
- protected void handleUpdateState(SignalState state, Object arg) {
- if (DEBUG) Log.d(TAG, "handleUpdateState arg=" + arg);
- final CallbackInfo cb = mSignalCallback.mInfo;
- if (mExpectDisabled) {
- if (cb.enabled) {
- return; // Ignore updates until disabled event occurs.
- } else {
- mExpectDisabled = false;
- }
- }
- boolean transientEnabling = arg == ARG_SHOW_TRANSIENT_ENABLING;
- boolean wifiConnected = cb.enabled && (cb.wifiSignalIconId > 0)
- && (cb.ssid != null || cb.wifiSignalIconId != WifiIcons.QS_WIFI_NO_NETWORK);
- boolean wifiNotConnected = (cb.ssid == null)
- && (cb.wifiSignalIconId == WifiIcons.QS_WIFI_NO_NETWORK);
- if (state.slash == null) {
- state.slash = new SlashState();
- state.slash.rotation = 6;
- }
- state.slash.isSlashed = false;
- boolean isTransient = transientEnabling || cb.isTransient;
- state.secondaryLabel = getSecondaryLabel(isTransient, cb.statusLabel);
- state.state = Tile.STATE_ACTIVE;
- state.dualTarget = true;
- state.value = transientEnabling || cb.enabled;
- state.activityIn = cb.enabled && cb.activityIn;
- state.activityOut = cb.enabled && cb.activityOut;
- final StringBuffer minimalContentDescription = new StringBuffer();
- final StringBuffer minimalStateDescription = new StringBuffer();
- final Resources r = mContext.getResources();
- if (isTransient) {
- state.icon = ResourceIcon.get(
- com.android.internal.R.drawable.ic_signal_wifi_transient_animation);
- state.label = r.getString(R.string.quick_settings_wifi_label);
- } else if (!state.value) {
- state.slash.isSlashed = true;
- state.state = Tile.STATE_INACTIVE;
- state.icon = ResourceIcon.get(WifiIcons.QS_WIFI_DISABLED);
- state.label = r.getString(R.string.quick_settings_wifi_label);
- } else if (wifiConnected) {
- state.icon = ResourceIcon.get(cb.wifiSignalIconId);
- state.label = cb.ssid != null ? removeDoubleQuotes(cb.ssid) : getTileLabel();
- } else if (wifiNotConnected) {
- state.icon = ResourceIcon.get(WifiIcons.QS_WIFI_NO_NETWORK);
- state.label = r.getString(R.string.quick_settings_wifi_label);
- } else {
- state.icon = ResourceIcon.get(WifiIcons.QS_WIFI_NO_NETWORK);
- state.label = r.getString(R.string.quick_settings_wifi_label);
- }
- minimalContentDescription.append(
- mContext.getString(R.string.quick_settings_wifi_label)).append(",");
- if (state.value) {
- if (wifiConnected) {
- minimalStateDescription.append(cb.wifiSignalContentDescription);
- minimalContentDescription.append(removeDoubleQuotes(cb.ssid));
- if (!TextUtils.isEmpty(state.secondaryLabel)) {
- minimalContentDescription.append(",").append(state.secondaryLabel);
- }
- }
- }
- state.stateDescription = minimalStateDescription.toString();
- state.contentDescription = minimalContentDescription.toString();
- state.dualLabelContentDescription = r.getString(
- R.string.accessibility_quick_settings_open_settings, getTileLabel());
- state.expandedAccessibilityClassName = Switch.class.getName();
- }
-
- private CharSequence getSecondaryLabel(boolean isTransient, String statusLabel) {
- return isTransient
- ? mContext.getString(R.string.quick_settings_wifi_secondary_label_transient)
- : statusLabel;
- }
-
- @Override
- public int getMetricsCategory() {
- return MetricsEvent.QS_WIFI;
- }
-
- @Override
- public boolean isAvailable() {
- return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI);
- }
-
- @Nullable
- private static String removeDoubleQuotes(String string) {
- if (string == null) return null;
- final int length = string.length();
- if ((length > 1) && (string.charAt(0) == '"') && (string.charAt(length - 1) == '"')) {
- return string.substring(1, length - 1);
- }
- return string;
- }
-
- protected static final class CallbackInfo {
- boolean enabled;
- boolean connected;
- int wifiSignalIconId;
- @Nullable
- String ssid;
- boolean activityIn;
- boolean activityOut;
- @Nullable
- String wifiSignalContentDescription;
- boolean isTransient;
- @Nullable
- public String statusLabel;
-
- @Override
- public String toString() {
- return new StringBuilder("CallbackInfo[")
- .append("enabled=").append(enabled)
- .append(",connected=").append(connected)
- .append(",wifiSignalIconId=").append(wifiSignalIconId)
- .append(",ssid=").append(ssid)
- .append(",activityIn=").append(activityIn)
- .append(",activityOut=").append(activityOut)
- .append(",wifiSignalContentDescription=").append(wifiSignalContentDescription)
- .append(",isTransient=").append(isTransient)
- .append(']').toString();
- }
- }
-
- protected final class WifiSignalCallback implements SignalCallback {
- final CallbackInfo mInfo = new CallbackInfo();
-
- @Override
- public void setWifiIndicators(@NonNull WifiIndicators indicators) {
- if (DEBUG) Log.d(TAG, "onWifiSignalChanged enabled=" + indicators.enabled);
- if (indicators.qsIcon == null) {
- return;
- }
- mInfo.enabled = indicators.enabled;
- mInfo.connected = indicators.qsIcon.visible;
- mInfo.wifiSignalIconId = indicators.qsIcon.icon;
- mInfo.ssid = indicators.description;
- mInfo.activityIn = indicators.activityIn;
- mInfo.activityOut = indicators.activityOut;
- mInfo.wifiSignalContentDescription = indicators.qsIcon.contentDescription;
- mInfo.isTransient = indicators.isTransient;
- mInfo.statusLabel = indicators.statusLabel;
- refreshState();
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
index a6c7781..72c6bfe 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
@@ -101,7 +101,6 @@
@MainThread
public void onManagedProfileRemoved() {
mHost.removeTile(getTileSpec());
- mHost.unmarkTileAsAutoAdded(getTileSpec());
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java
index 5ea1c0b..c335a6d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java
@@ -59,11 +59,11 @@
}
@Override
- public void showRecentApps(boolean triggeredFromAltTab) {
+ public void showRecentApps(boolean triggeredFromAltTab, boolean forward) {
IOverviewProxy overviewProxy = mOverviewProxyService.getProxy();
if (overviewProxy != null) {
try {
- overviewProxy.onOverviewShown(triggeredFromAltTab);
+ overviewProxy.onOverviewShown(triggeredFromAltTab, forward);
} catch (RemoteException e) {
Log.e(TAG, "Failed to send overview show event to launcher.", e);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index b041f95..95d6c18 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -65,14 +65,14 @@
}
@Override
- public void showRecentApps(boolean triggeredFromAltTab) {
+ public void showRecentApps(boolean triggeredFromAltTab, boolean forward) {
// Ensure the device has been provisioned before allowing the user to interact with
// recents
if (!isUserSetup()) {
return;
}
- mImpl.showRecentApps(triggeredFromAltTab);
+ mImpl.showRecentApps(triggeredFromAltTab, forward);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImplementation.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImplementation.java
index 8848dbb..010ceda 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImplementation.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImplementation.java
@@ -31,7 +31,7 @@
default void preloadRecentApps() {}
default void cancelPreloadRecentApps() {}
- default void showRecentApps(boolean triggeredFromAltTab) {}
+ default void showRecentApps(boolean triggeredFromAltTab, boolean forward) {}
default void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {}
default void toggleRecentApps() {}
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt
index 44b18ec..68e3dcd 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt
@@ -23,6 +23,7 @@
import android.os.Handler
import android.os.Looper
import android.os.ResultReceiver
+import android.os.UserHandle
import android.view.View
import android.view.View.GONE
import android.view.View.VISIBLE
@@ -77,6 +78,14 @@
MediaProjectionAppSelectorActivity.EXTRA_CAPTURE_REGION_RESULT_RECEIVER,
CaptureTargetResultReceiver()
)
+
+ // Send SystemUI's user handle as the host app user handle because SystemUI
+ // is the 'host app' (the app that receives screen capture data)
+ intent.putExtra(
+ MediaProjectionAppSelectorActivity.EXTRA_HOST_APP_USER_HANDLE,
+ UserHandle.of(UserHandle.myUserId())
+ )
+
val animationController = dialogLaunchAnimator.createActivityLaunchController(v!!)
if (animationController == null) {
dismiss()
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index 91ebf79..b21a485 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -687,8 +687,8 @@
}
});
if (mFlags.isEnabled(SCREENSHOT_WORK_PROFILE_POLICY)) {
- mScreenshotView.badgeScreenshot(
- mContext.getPackageManager().getUserBadgeForDensity(owner, 0));
+ mScreenshotView.badgeScreenshot(mContext.getPackageManager().getUserBadgedIcon(
+ mContext.getDrawable(R.drawable.overlay_badge_background), owner));
}
mScreenshotView.setScreenshot(mScreenBitmap, screenInsets);
if (DEBUG_WINDOW) {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
index be40813..7c013a8 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
@@ -1097,7 +1097,7 @@
mScreenshotBadge.setVisibility(View.GONE);
mScreenshotBadge.setImageDrawable(null);
mPendingSharedTransition = false;
- mActionsContainerBackground.setVisibility(View.GONE);
+ mActionsContainerBackground.setVisibility(View.INVISIBLE);
mActionsContainer.setVisibility(View.GONE);
mDismissButton.setVisibility(View.GONE);
mScrollingScrim.setVisibility(View.GONE);
diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
index 200288b..4dbe099 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
@@ -111,7 +111,7 @@
// These get called when a managed profile goes in or out of quiet mode.
addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE)
addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE)
-
+ addAction(Intent.ACTION_MANAGED_PROFILE_ADDED)
addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED)
addAction(Intent.ACTION_MANAGED_PROFILE_UNLOCKED)
}
@@ -128,6 +128,7 @@
Intent.ACTION_USER_INFO_CHANGED,
Intent.ACTION_MANAGED_PROFILE_AVAILABLE,
Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE,
+ Intent.ACTION_MANAGED_PROFILE_ADDED,
Intent.ACTION_MANAGED_PROFILE_REMOVED,
Intent.ACTION_MANAGED_PROFILE_UNLOCKED -> {
handleProfilesChanged()
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index b48fd98..fd31e49 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -144,6 +144,7 @@
import com.android.systemui.keyguard.shared.model.TransitionState;
import com.android.systemui.keyguard.shared.model.TransitionStep;
import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
+import com.android.systemui.keyguard.ui.viewmodel.GoneToDreamingTransitionViewModel;
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBottomAreaViewModel;
import com.android.systemui.keyguard.ui.viewmodel.LockscreenToDreamingTransitionViewModel;
import com.android.systemui.keyguard.ui.viewmodel.LockscreenToOccludedTransitionViewModel;
@@ -692,6 +693,7 @@
private DreamingToLockscreenTransitionViewModel mDreamingToLockscreenTransitionViewModel;
private OccludedToLockscreenTransitionViewModel mOccludedToLockscreenTransitionViewModel;
private LockscreenToDreamingTransitionViewModel mLockscreenToDreamingTransitionViewModel;
+ private GoneToDreamingTransitionViewModel mGoneToDreamingTransitionViewModel;
private LockscreenToOccludedTransitionViewModel mLockscreenToOccludedTransitionViewModel;
private KeyguardTransitionInteractor mKeyguardTransitionInteractor;
@@ -700,6 +702,7 @@
private int mDreamingToLockscreenTransitionTranslationY;
private int mOccludedToLockscreenTransitionTranslationY;
private int mLockscreenToDreamingTransitionTranslationY;
+ private int mGoneToDreamingTransitionTranslationY;
private int mLockscreenToOccludedTransitionTranslationY;
private boolean mUnocclusionTransitionFlagEnabled = false;
@@ -712,7 +715,7 @@
updatePanelExpansionAndVisibility();
};
private final Runnable mMaybeHideExpandedRunnable = () -> {
- if (getExpansionFraction() == 0.0f) {
+ if (getExpandedFraction() == 0.0f) {
postToView(mHideExpandedRunnable);
}
};
@@ -735,6 +738,12 @@
step.getTransitionState() == TransitionState.RUNNING;
};
+ private final Consumer<TransitionStep> mGoneToDreamingTransition =
+ (TransitionStep step) -> {
+ mIsOcclusionTransitionRunning =
+ step.getTransitionState() == TransitionState.RUNNING;
+ };
+
private final Consumer<TransitionStep> mLockscreenToOccludedTransition =
(TransitionStep step) -> {
mIsOcclusionTransitionRunning =
@@ -813,6 +822,7 @@
DreamingToLockscreenTransitionViewModel dreamingToLockscreenTransitionViewModel,
OccludedToLockscreenTransitionViewModel occludedToLockscreenTransitionViewModel,
LockscreenToDreamingTransitionViewModel lockscreenToDreamingTransitionViewModel,
+ GoneToDreamingTransitionViewModel goneToDreamingTransitionViewModel,
LockscreenToOccludedTransitionViewModel lockscreenToOccludedTransitionViewModel,
@Main CoroutineDispatcher mainDispatcher,
KeyguardTransitionInteractor keyguardTransitionInteractor,
@@ -834,6 +844,7 @@
mDreamingToLockscreenTransitionViewModel = dreamingToLockscreenTransitionViewModel;
mOccludedToLockscreenTransitionViewModel = occludedToLockscreenTransitionViewModel;
mLockscreenToDreamingTransitionViewModel = lockscreenToDreamingTransitionViewModel;
+ mGoneToDreamingTransitionViewModel = goneToDreamingTransitionViewModel;
mLockscreenToOccludedTransitionViewModel = lockscreenToOccludedTransitionViewModel;
mKeyguardTransitionInteractor = keyguardTransitionInteractor;
mView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
@@ -1172,6 +1183,17 @@
setTransitionY(mNotificationStackScrollLayoutController),
mMainDispatcher);
+ // Gone->Dreaming
+ collectFlow(mView, mKeyguardTransitionInteractor.getGoneToDreamingTransition(),
+ mGoneToDreamingTransition, mMainDispatcher);
+ collectFlow(mView, mGoneToDreamingTransitionViewModel.getLockscreenAlpha(),
+ setTransitionAlpha(mNotificationStackScrollLayoutController),
+ mMainDispatcher);
+ collectFlow(mView, mGoneToDreamingTransitionViewModel.lockscreenTranslationY(
+ mGoneToDreamingTransitionTranslationY),
+ setTransitionY(mNotificationStackScrollLayoutController),
+ mMainDispatcher);
+
// Lockscreen->Occluded
collectFlow(mView, mKeyguardTransitionInteractor.getLockscreenToOccludedTransition(),
mLockscreenToOccludedTransition, mMainDispatcher);
@@ -1223,6 +1245,8 @@
R.dimen.occluded_to_lockscreen_transition_lockscreen_translation_y);
mLockscreenToDreamingTransitionTranslationY = mResources.getDimensionPixelSize(
R.dimen.lockscreen_to_dreaming_transition_lockscreen_translation_y);
+ mGoneToDreamingTransitionTranslationY = mResources.getDimensionPixelSize(
+ R.dimen.gone_to_dreaming_transition_lockscreen_translation_y);
mLockscreenToOccludedTransitionTranslationY = mResources.getDimensionPixelSize(
R.dimen.lockscreen_to_occluded_transition_lockscreen_translation_y);
}
@@ -2340,7 +2364,7 @@
// When false, down but not synthesized motion event.
mLastEventSynthesizedDown = mExpectingSynthesizedDown;
mLastDownEvents.insert(
- mSystemClock.currentTimeMillis(),
+ event.getEventTime(),
mDownX,
mDownY,
mQsTouchAboveFalsingThreshold,
@@ -2473,7 +2497,7 @@
mInitialTouchY = event.getY();
mInitialTouchX = event.getX();
}
- if (!isFullyCollapsed()) {
+ if (!isFullyCollapsed() && !isShadeOrQsHeightAnimationRunning()) {
handleQsDown(event);
}
// defer touches on QQS to shade while shade is collapsing. Added margin for error
@@ -5263,6 +5287,11 @@
}
}
+ /** Returns whether a shade or QS expansion animation is running */
+ private boolean isShadeOrQsHeightAnimationRunning() {
+ return mHeightAnimator != null && !mHintAnimationRunning && !mIsSpringBackAnimation;
+ }
+
/**
* Phase 2: Bounce down.
*/
@@ -5422,10 +5451,6 @@
InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE);
}
- private float getExpansionFraction() {
- return mExpandedFraction;
- }
-
private ShadeExpansionStateManager getShadeExpansionStateManager() {
return mShadeExpansionStateManager;
}
@@ -6280,8 +6305,7 @@
mCollapsedAndHeadsUpOnDown =
isFullyCollapsed() && mHeadsUpManager.hasPinnedHeadsUp();
addMovement(event);
- boolean regularHeightAnimationRunning = mHeightAnimator != null
- && !mHintAnimationRunning && !mIsSpringBackAnimation;
+ boolean regularHeightAnimationRunning = isShadeOrQsHeightAnimationRunning();
if (!mGestureWaitForTouchSlop || regularHeightAnimationRunning) {
mTouchSlopExceeded = regularHeightAnimationRunning
|| mTouchSlopExceededBeforeDown;
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
index 8314ec7..26f8b62 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
@@ -321,9 +321,12 @@
&& !state.mKeyguardFadingAway && !state.mKeyguardGoingAway;
if (onKeyguard
&& mAuthController.isUdfpsEnrolled(KeyguardUpdateMonitor.getCurrentUser())) {
+ // both max and min display refresh rate must be set to take effect:
mLpChanged.preferredMaxDisplayRefreshRate = mKeyguardPreferredRefreshRate;
+ mLpChanged.preferredMinDisplayRefreshRate = mKeyguardPreferredRefreshRate;
} else {
mLpChanged.preferredMaxDisplayRefreshRate = 0;
+ mLpChanged.preferredMinDisplayRefreshRate = 0;
}
Trace.setCounter("display_set_preferred_refresh_rate",
(long) mKeyguardPreferredRefreshRate);
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java
index ca03127..f712629 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java
@@ -58,6 +58,7 @@
import com.android.internal.view.FloatingActionMode;
import com.android.internal.widget.floatingtoolbar.FloatingToolbar;
import com.android.systemui.R;
+import com.android.systemui.compose.ComposeFacade;
/**
* Combined keyguard and notification panel view. Also holding backdrop and scrims.
@@ -149,6 +150,18 @@
protected void onAttachedToWindow() {
super.onAttachedToWindow();
setWillNotDraw(!DEBUG);
+
+ if (ComposeFacade.INSTANCE.isComposeAvailable()) {
+ ComposeFacade.INSTANCE.composeInitializer().onAttachedToWindow(this);
+ }
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ if (ComposeFacade.INSTANCE.isComposeAvailable()) {
+ ComposeFacade.INSTANCE.composeInitializer().onDetachedFromWindow(this);
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
index 5fedbeb..11617be 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
@@ -36,16 +36,9 @@
buffer.log(TAG, LogLevel.DEBUG, msg)
}
- private inline fun log(
- logLevel: LogLevel,
- initializer: LogMessage.() -> Unit,
- noinline printer: LogMessage.() -> String
- ) {
- buffer.log(TAG, logLevel, initializer, printer)
- }
-
fun onQsInterceptMoveQsTrackingEnabled(h: Float) {
- log(
+ buffer.log(
+ TAG,
LogLevel.VERBOSE,
{ double1 = h.toDouble() },
{ "onQsIntercept: move action, QS tracking enabled. h = $double1" }
@@ -62,7 +55,8 @@
keyguardShowing: Boolean,
qsExpansionEnabled: Boolean
) {
- log(
+ buffer.log(
+ TAG,
LogLevel.VERBOSE,
{
int1 = initialTouchY.toInt()
@@ -82,7 +76,8 @@
}
fun logMotionEvent(event: MotionEvent, message: String) {
- log(
+ buffer.log(
+ TAG,
LogLevel.VERBOSE,
{
str1 = message
@@ -99,7 +94,8 @@
}
fun logMotionEventStatusBarState(event: MotionEvent, statusBarState: Int, message: String) {
- log(
+ buffer.log(
+ TAG,
LogLevel.VERBOSE,
{
str1 = message
@@ -128,25 +124,33 @@
tracking: Boolean,
dragDownPxAmount: Float,
) {
- log(LogLevel.VERBOSE, {
- str1 = message
- double1 = fraction.toDouble()
- bool1 = expanded
- bool2 = tracking
- long1 = dragDownPxAmount.toLong()
- }, {
- "$str1 fraction=$double1,expanded=$bool1," +
+ buffer.log(
+ TAG,
+ LogLevel.VERBOSE,
+ {
+ str1 = message
+ double1 = fraction.toDouble()
+ bool1 = expanded
+ bool2 = tracking
+ long1 = dragDownPxAmount.toLong()
+ },
+ {
+ "$str1 fraction=$double1,expanded=$bool1," +
"tracking=$bool2," + "dragDownPxAmount=$dragDownPxAmount"
- })
+ }
+ )
}
fun logHasVibrated(hasVibratedOnOpen: Boolean, fraction: Float) {
- log(LogLevel.VERBOSE, {
- bool1 = hasVibratedOnOpen
- double1 = fraction.toDouble()
- }, {
- "hasVibratedOnOpen=$bool1, expansionFraction=$double1"
- })
+ buffer.log(
+ TAG,
+ LogLevel.VERBOSE,
+ {
+ bool1 = hasVibratedOnOpen
+ double1 = fraction.toDouble()
+ },
+ { "hasVibratedOnOpen=$bool1, expansionFraction=$double1" }
+ )
}
fun logQsExpansionChanged(
@@ -159,42 +163,56 @@
qsAnimatorExpand: Boolean,
animatingQs: Boolean
) {
- log(LogLevel.VERBOSE, {
- str1 = message
- bool1 = qsExpanded
- int1 = qsMinExpansionHeight
- int2 = qsMaxExpansionHeight
- bool2 = stackScrollerOverscrolling
- bool3 = dozing
- bool4 = qsAnimatorExpand
- // 0 = false, 1 = true
- long1 = animatingQs.compareTo(false).toLong()
- }, {
- "$str1 qsExpanded=$bool1,qsMinExpansionHeight=$int1,qsMaxExpansionHeight=$int2," +
+ buffer.log(
+ TAG,
+ LogLevel.VERBOSE,
+ {
+ str1 = message
+ bool1 = qsExpanded
+ int1 = qsMinExpansionHeight
+ int2 = qsMaxExpansionHeight
+ bool2 = stackScrollerOverscrolling
+ bool3 = dozing
+ bool4 = qsAnimatorExpand
+ // 0 = false, 1 = true
+ long1 = animatingQs.compareTo(false).toLong()
+ },
+ {
+ "$str1 qsExpanded=$bool1,qsMinExpansionHeight=$int1,qsMaxExpansionHeight=$int2," +
"stackScrollerOverscrolling=$bool2,dozing=$bool3,qsAnimatorExpand=$bool4," +
"animatingQs=$long1"
- })
+ }
+ )
}
fun logSingleTapUp(isDozing: Boolean, singleTapEnabled: Boolean, isNotDocked: Boolean) {
- log(LogLevel.DEBUG, {
- bool1 = isDozing
- bool2 = singleTapEnabled
- bool3 = isNotDocked
- }, {
- "PulsingGestureListener#onSingleTapUp all of this must true for single " +
- "tap to be detected: isDozing: $bool1, singleTapEnabled: $bool2, isNotDocked: $bool3"
+ buffer.log(
+ TAG,
+ LogLevel.DEBUG,
+ {
+ bool1 = isDozing
+ bool2 = singleTapEnabled
+ bool3 = isNotDocked
+ },
+ {
+ "PulsingGestureListener#onSingleTapUp all of this must true for single " +
+ "tap to be detected: isDozing: $bool1, singleTapEnabled: $bool2, isNotDocked: $bool3"
})
}
fun logSingleTapUpFalsingState(proximityIsNotNear: Boolean, isNotFalseTap: Boolean) {
- log(LogLevel.DEBUG, {
- bool1 = proximityIsNotNear
- bool2 = isNotFalseTap
- }, {
- "PulsingGestureListener#onSingleTapUp all of this must true for single " +
+ buffer.log(
+ TAG,
+ LogLevel.DEBUG,
+ {
+ bool1 = proximityIsNotNear
+ bool2 = isNotFalseTap
+ },
+ {
+ "PulsingGestureListener#onSingleTapUp all of this must true for single " +
"tap to be detected: proximityIsNotNear: $bool1, isNotFalseTap: $bool2"
- })
+ }
+ )
}
fun logNotInterceptingTouchInstantExpanding(
@@ -202,13 +220,18 @@
notificationsDragEnabled: Boolean,
touchDisabled: Boolean
) {
- log(LogLevel.VERBOSE, {
- bool1 = instantExpanding
- bool2 = notificationsDragEnabled
- bool3 = touchDisabled
- }, {
- "NPVC not intercepting touch, instantExpanding: $bool1, " +
+ buffer.log(
+ TAG,
+ LogLevel.VERBOSE,
+ {
+ bool1 = instantExpanding
+ bool2 = notificationsDragEnabled
+ bool3 = touchDisabled
+ },
+ {
+ "NPVC not intercepting touch, instantExpanding: $bool1, " +
"!notificationsDragEnabled: $bool2, touchDisabled: $bool3"
- })
+ }
+ )
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeWindowLogger.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeWindowLogger.kt
index c6a6e87..9851625 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeWindowLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeWindowLogger.kt
@@ -32,11 +32,21 @@
ConstantStringsLogger by ConstantStringsLoggerImpl(buffer, TAG) {
fun logApplyingWindowLayoutParams(lp: WindowManager.LayoutParams) {
- log(DEBUG, { str1 = lp.toString() }, { "Applying new window layout params: $str1" })
+ buffer.log(
+ TAG,
+ DEBUG,
+ { str1 = lp.toString() },
+ { "Applying new window layout params: $str1" }
+ )
}
fun logNewState(state: Any) {
- log(DEBUG, { str1 = state.toString() }, { "Applying new state: $str1" })
+ buffer.log(
+ TAG,
+ DEBUG,
+ { str1 = state.toString() },
+ { "Applying new state: $str1" }
+ )
}
private inline fun log(
@@ -48,11 +58,16 @@
}
fun logApplyVisibility(visible: Boolean) {
- log(DEBUG, { bool1 = visible }, { "Updating visibility, should be visible : $bool1" })
+ buffer.log(
+ TAG,
+ DEBUG,
+ { bool1 = visible },
+ { "Updating visibility, should be visible : $bool1" })
}
fun logShadeVisibleAndFocusable(visible: Boolean) {
- log(
+ buffer.log(
+ TAG,
DEBUG,
{ bool1 = visible },
{ "Updating shade, should be visible and focusable: $bool1" }
@@ -60,6 +75,11 @@
}
fun logShadeFocusable(focusable: Boolean) {
- log(DEBUG, { bool1 = focusable }, { "Updating shade, should be focusable : $bool1" })
+ buffer.log(
+ TAG,
+ DEBUG,
+ { bool1 = focusable },
+ { "Updating shade, should be focusable : $bool1" }
+ )
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AlphaOptimizedFrameLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/AlphaOptimizedFrameLayout.java
index 662f70e..438b0f6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/AlphaOptimizedFrameLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/AlphaOptimizedFrameLayout.java
@@ -36,10 +36,6 @@
visibility -> {
super.setVisibility(visibility);
return Unit.INSTANCE;
- },
- visibility -> {
- super.setTransitionVisibility(visibility);
- return Unit.INSTANCE;
});
public AlphaOptimizedFrameLayout(Context context) {
@@ -73,9 +69,4 @@
public void setVisibility(int visibility) {
mLaunchableViewDelegate.setVisibility(visibility);
}
-
- @Override
- public void setTransitionVisibility(int visibility) {
- mLaunchableViewDelegate.setTransitionVisibility(visibility);
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index bad942f..04adaae 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -224,7 +224,7 @@
*/
default void setImeWindowStatus(int displayId, IBinder token, int vis,
@BackDispositionMode int backDisposition, boolean showImeSwitcher) { }
- default void showRecentApps(boolean triggeredFromAltTab) { }
+ default void showRecentApps(boolean triggeredFromAltTab, boolean forward) { }
default void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) { }
default void toggleRecentApps() { }
default void toggleSplitScreen() { }
@@ -686,11 +686,11 @@
}
}
- public void showRecentApps(boolean triggeredFromAltTab) {
+ public void showRecentApps(boolean triggeredFromAltTab, boolean forward) {
synchronized (mLock) {
mHandler.removeMessages(MSG_SHOW_RECENT_APPS);
- mHandler.obtainMessage(MSG_SHOW_RECENT_APPS, triggeredFromAltTab ? 1 : 0, 0,
- null).sendToTarget();
+ mHandler.obtainMessage(MSG_SHOW_RECENT_APPS, triggeredFromAltTab ? 1 : 0,
+ forward ? 1 : 0, null).sendToTarget();
}
}
@@ -1384,7 +1384,7 @@
break;
case MSG_SHOW_RECENT_APPS:
for (int i = 0; i < mCallbacks.size(); i++) {
- mCallbacks.get(i).showRecentApps(msg.arg1 != 0);
+ mCallbacks.get(i).showRecentApps(msg.arg1 != 0, msg.arg2 != 0);
}
break;
case MSG_HIDE_RECENT_APPS:
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
index 8f9365c..99081e9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
@@ -65,8 +65,6 @@
import com.android.systemui.util.DumpUtilsKt;
import com.android.systemui.util.ListenerSet;
-import dagger.Lazy;
-
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
@@ -74,6 +72,8 @@
import java.util.Optional;
import java.util.function.Consumer;
+import dagger.Lazy;
+
/**
* Class for handling remote input state over a set of notifications. This class handles things
* like keeping notifications temporarily that were cancelled as a response to a remote input
@@ -465,8 +465,7 @@
riv.getController().setRemoteInput(input);
riv.getController().setRemoteInputs(inputs);
riv.getController().setEditedSuggestionInfo(editedSuggestionInfo);
- ViewGroup parent = view.getParent() != null ? (ViewGroup) view.getParent() : null;
- riv.focusAnimated(parent);
+ riv.focusAnimated();
if (userMessageContent != null) {
riv.setEditTextContent(userMessageContent);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt
index 1e7fc93..197cf56 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt
@@ -54,7 +54,7 @@
* their respective views based on the progress of the animator. Interpolation differences TBD
*/
@SysUISingleton
-class SystemStatusAnimationScheduler @Inject constructor(
+open class SystemStatusAnimationScheduler @Inject constructor(
private val coordinator: SystemEventCoordinator,
private val chipAnimationController: SystemEventChipAnimationController,
private val statusBarWindowController: StatusBarWindowController,
@@ -66,7 +66,7 @@
companion object {
private const val PROPERTY_ENABLE_IMMERSIVE_INDICATOR = "enable_immersive_indicator"
}
- private fun isImmersiveIndicatorEnabled(): Boolean {
+ public fun isImmersiveIndicatorEnabled(): Boolean {
return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
PROPERTY_ENABLE_IMMERSIVE_INDICATOR, true)
}
@@ -76,18 +76,22 @@
/** True if the persistent privacy dot should be active */
var hasPersistentDot = false
- private set
+ protected set
private var scheduledEvent: StatusEvent? = null
private var cancelExecutionRunnable: Runnable? = null
private val listeners = mutableSetOf<SystemStatusAnimationCallback>()
+ fun getListeners(): MutableSet<SystemStatusAnimationCallback> {
+ return listeners
+ }
+
init {
coordinator.attachScheduler(this)
dumpManager.registerDumpable(TAG, this)
}
- fun onStatusEvent(event: StatusEvent) {
+ open fun onStatusEvent(event: StatusEvent) {
// Ignore any updates until the system is up and running
if (isTooEarly() || !isImmersiveIndicatorEnabled()) {
return
@@ -139,7 +143,7 @@
}
}
- private fun isTooEarly(): Boolean {
+ public fun isTooEarly(): Boolean {
return systemClock.uptimeMillis() - Process.getStartUptimeMillis() < MIN_UPTIME
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewController.java
index c496102..b084a76 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewController.java
@@ -109,7 +109,7 @@
return true;
}
if (ev.getAction() == MotionEvent.ACTION_UP) {
- mView.setLastActionUpTime(SystemClock.uptimeMillis());
+ mView.setLastActionUpTime(ev.getEventTime());
}
// With a11y, just do nothing.
if (mAccessibilityManager.isTouchExplorationEnabled()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index ca1e397..356ddfa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -1811,9 +1811,7 @@
@Override
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
- mBottomInset = insets.getSystemWindowInsetBottom()
- + insets.getInsets(WindowInsets.Type.ime()).bottom;
-
+ mBottomInset = insets.getInsets(WindowInsets.Type.ime()).bottom;
mWaterfallTopInset = 0;
final DisplayCutout cutout = insets.getDisplayCutout();
if (cutout != null) {
@@ -2262,7 +2260,11 @@
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
private int getImeInset() {
- return Math.max(0, mBottomInset - (getRootView().getHeight() - getHeight()));
+ // The NotificationStackScrollLayout does not extend all the way to the bottom of the
+ // display. Therefore, subtract that space from the mBottomInset, in order to only include
+ // the portion of the bottom inset that actually overlaps the NotificationStackScrollLayout.
+ return Math.max(0, mBottomInset
+ - (getRootView().getHeight() - getHeight() - getLocationOnScreen()[1]));
}
/**
@@ -2970,12 +2972,19 @@
childInGroup = (ExpandableNotificationRow) requestedView;
requestedView = requestedRow = childInGroup.getNotificationParent();
}
- int position = 0;
+ final float scrimTopPadding = mAmbientState.isOnKeyguard() ? 0 : mMinimumPaddings;
+ int position = (int) scrimTopPadding;
+ int visibleIndex = -1;
+ ExpandableView lastVisibleChild = null;
for (int i = 0; i < getChildCount(); i++) {
ExpandableView child = getChildAtIndex(i);
boolean notGone = child.getVisibility() != View.GONE;
+ if (notGone) visibleIndex++;
if (notGone && !child.hasNoContentHeight()) {
- if (position != 0) {
+ if (position != scrimTopPadding) {
+ if (lastVisibleChild != null) {
+ position += calculateGapHeight(lastVisibleChild, child, visibleIndex);
+ }
position += mPaddingBetweenElements;
}
}
@@ -2987,6 +2996,7 @@
}
if (notGone) {
position += getIntrinsicHeight(child);
+ lastVisibleChild = child;
}
}
return 0;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java
index 3ccef9d..eb81c46 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java
@@ -16,25 +16,35 @@
package com.android.systemui.statusbar.phone;
+import static android.view.accessibility.AccessibilityManager.FLAG_CONTENT_CONTROLS;
+
import android.content.Context;
import android.os.Handler;
import android.os.RemoteException;
import android.util.Log;
import android.view.IWindowManager;
import android.view.MotionEvent;
+import android.view.accessibility.AccessibilityManager;
+
+import androidx.annotation.NonNull;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.dump.DumpManager;
import com.android.systemui.statusbar.AutoHideUiElement;
+import java.io.PrintWriter;
+
import javax.inject.Inject;
/** A controller to control all auto-hide things. Also see {@link AutoHideUiElement}. */
@SysUISingleton
public class AutoHideController {
private static final String TAG = "AutoHideController";
- private static final long AUTO_HIDE_TIMEOUT_MS = 2250;
+ private static final int AUTO_HIDE_TIMEOUT_MS = 2250;
+ private static final int USER_AUTO_HIDE_TIMEOUT_MS = 350;
+ private final AccessibilityManager mAccessibilityManager;
private final IWindowManager mWindowManagerService;
private final Handler mHandler;
@@ -52,11 +62,12 @@
};
@Inject
- public AutoHideController(Context context, @Main Handler handler,
+ public AutoHideController(Context context,
+ @Main Handler handler,
IWindowManager iWindowManager) {
+ mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
mHandler = handler;
mWindowManagerService = iWindowManager;
-
mDisplayId = context.getDisplayId();
}
@@ -138,7 +149,12 @@
private void scheduleAutoHide() {
cancelAutoHide();
- mHandler.postDelayed(mAutoHide, AUTO_HIDE_TIMEOUT_MS);
+ mHandler.postDelayed(mAutoHide, getAutoHideTimeout());
+ }
+
+ private int getAutoHideTimeout() {
+ return mAccessibilityManager.getRecommendedTimeoutMillis(AUTO_HIDE_TIMEOUT_MS,
+ FLAG_CONTENT_CONTROLS);
}
public void checkUserAutoHide(MotionEvent event) {
@@ -160,7 +176,13 @@
private void userAutoHide() {
cancelAutoHide();
- mHandler.postDelayed(mAutoHide, 350); // longer than app gesture -> flag clear
+ // longer than app gesture -> flag clear
+ mHandler.postDelayed(mAutoHide, getUserAutoHideTimeout());
+ }
+
+ private int getUserAutoHideTimeout() {
+ return mAccessibilityManager.getRecommendedTimeoutMillis(USER_AUTO_HIDE_TIMEOUT_MS,
+ FLAG_CONTENT_CONTROLS);
}
private boolean isAnyTransientBarShown() {
@@ -175,6 +197,15 @@
return false;
}
+ public void dump(@NonNull PrintWriter pw) {
+ pw.println("AutoHideController:");
+ pw.println("\tmAutoHideSuspended=" + mAutoHideSuspended);
+ pw.println("\tisAnyTransientBarShown=" + isAnyTransientBarShown());
+ pw.println("\thasPendingAutoHide=" + mHandler.hasCallbacks(mAutoHide));
+ pw.println("\tgetAutoHideTimeout=" + getAutoHideTimeout());
+ pw.println("\tgetUserAutoHideTimeout=" + getUserAutoHideTimeout());
+ }
+
/**
* Injectable factory for creating a {@link AutoHideController}.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
index 9070ead..149ec54 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
@@ -154,9 +154,7 @@
if (!mAutoTracker.isAdded(SAVER)) {
mDataSaverController.addCallback(mDataSaverListener);
}
- if (!mAutoTracker.isAdded(WORK)) {
- mManagedProfileController.addCallback(mProfileCallback);
- }
+ mManagedProfileController.addCallback(mProfileCallback);
if (!mAutoTracker.isAdded(NIGHT)
&& ColorDisplayManager.isNightDisplayAvailable(mContext)) {
mNightDisplayListener.setCallback(mNightDisplayCallback);
@@ -275,18 +273,18 @@
return mCurrentUser.getIdentifier();
}
- public void unmarkTileAsAutoAdded(String tabSpec) {
- mAutoTracker.setTileRemoved(tabSpec);
- }
-
private final ManagedProfileController.Callback mProfileCallback =
new ManagedProfileController.Callback() {
@Override
public void onManagedProfileChanged() {
- if (mAutoTracker.isAdded(WORK)) return;
if (mManagedProfileController.hasActiveProfile()) {
+ if (mAutoTracker.isAdded(WORK)) return;
mHost.addTile(WORK);
mAutoTracker.setTileAdded(WORK);
+ } else {
+ if (!mAutoTracker.isAdded(WORK)) return;
+ mHost.removeTile(WORK);
+ mAutoTracker.setTileRemoved(WORK);
}
}
@@ -429,7 +427,7 @@
initSafetyTile();
} else if (!isSafetyCenterEnabled && mAutoTracker.isAdded(mSafetySpec)) {
mHost.removeTile(mSafetySpec);
- mHost.unmarkTileAsAutoAdded(mSafetySpec);
+ mAutoTracker.setTileRemoved(mSafetySpec);
}
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index 9a8c5d7..9f38361 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -18,6 +18,8 @@
import static android.app.StatusBarManager.SESSION_KEYGUARD;
+import static com.android.systemui.keyguard.WakefulnessLifecycle.UNKNOWN_LAST_WAKE_TIME;
+
import android.annotation.IntDef;
import android.content.res.Resources;
import android.hardware.biometrics.BiometricFaceConstants;
@@ -27,7 +29,6 @@
import android.metrics.LogMaker;
import android.os.Handler;
import android.os.PowerManager;
-import android.os.SystemClock;
import android.os.Trace;
import androidx.annotation.Nullable;
@@ -59,6 +60,7 @@
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.util.time.SystemClock;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
@@ -75,6 +77,7 @@
*/
@SysUISingleton
public class BiometricUnlockController extends KeyguardUpdateMonitorCallback implements Dumpable {
+ private static final long RECENT_POWER_BUTTON_PRESS_THRESHOLD_MS = 400L;
private static final long BIOMETRIC_WAKELOCK_TIMEOUT_MS = 15 * 1000;
private static final String BIOMETRIC_WAKE_LOCK_NAME = "wake-and-unlock:wakelock";
private static final UiEventLogger UI_EVENT_LOGGER = new UiEventLoggerImpl();
@@ -165,9 +168,11 @@
private final MetricsLogger mMetricsLogger;
private final AuthController mAuthController;
private final StatusBarStateController mStatusBarStateController;
+ private final WakefulnessLifecycle mWakefulnessLifecycle;
private final LatencyTracker mLatencyTracker;
private final VibratorHelper mVibratorHelper;
private final BiometricUnlockLogger mLogger;
+ private final SystemClock mSystemClock;
private long mLastFpFailureUptimeMillis;
private int mNumConsecutiveFpFailures;
@@ -272,13 +277,16 @@
SessionTracker sessionTracker,
LatencyTracker latencyTracker,
ScreenOffAnimationController screenOffAnimationController,
- VibratorHelper vibrator) {
+ VibratorHelper vibrator,
+ SystemClock systemClock
+ ) {
mPowerManager = powerManager;
mUpdateMonitor = keyguardUpdateMonitor;
mUpdateMonitor.registerCallback(this);
mMediaManager = notificationMediaManager;
mLatencyTracker = latencyTracker;
- wakefulnessLifecycle.addObserver(mWakefulnessObserver);
+ mWakefulnessLifecycle = wakefulnessLifecycle;
+ mWakefulnessLifecycle.addObserver(mWakefulnessObserver);
screenLifecycle.addObserver(mScreenObserver);
mNotificationShadeWindowController = notificationShadeWindowController;
@@ -297,6 +305,7 @@
mScreenOffAnimationController = screenOffAnimationController;
mVibratorHelper = vibrator;
mLogger = biometricUnlockLogger;
+ mSystemClock = systemClock;
dumpManager.registerDumpable(getClass().getName(), this);
}
@@ -420,8 +429,11 @@
Runnable wakeUp = ()-> {
if (!wasDeviceInteractive || mUpdateMonitor.isDreaming()) {
mLogger.i("bio wakelock: Authenticated, waking up...");
- mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_BIOMETRIC,
- "android.policy:BIOMETRIC");
+ mPowerManager.wakeUp(
+ mSystemClock.uptimeMillis(),
+ PowerManager.WAKE_REASON_BIOMETRIC,
+ "android.policy:BIOMETRIC"
+ );
}
Trace.beginSection("release wake-and-unlock");
releaseBiometricWakeLock();
@@ -652,7 +664,7 @@
startWakeAndUnlock(MODE_ONLY_WAKE);
} else if (biometricSourceType == BiometricSourceType.FINGERPRINT
&& mUpdateMonitor.isUdfpsSupported()) {
- long currUptimeMillis = SystemClock.uptimeMillis();
+ long currUptimeMillis = mSystemClock.uptimeMillis();
if (currUptimeMillis - mLastFpFailureUptimeMillis < mConsecutiveFpFailureThreshold) {
mNumConsecutiveFpFailures += 1;
} else {
@@ -700,12 +712,26 @@
cleanup();
}
- //these haptics are for device-entry only
+ // these haptics are for device-entry only
private void vibrateSuccess(BiometricSourceType type) {
+ if (mAuthController.isSfpsEnrolled(KeyguardUpdateMonitor.getCurrentUser())
+ && lastWakeupFromPowerButtonWithinHapticThreshold()) {
+ mLogger.d("Skip auth success haptic. Power button was recently pressed.");
+ return;
+ }
mVibratorHelper.vibrateAuthSuccess(
getClass().getSimpleName() + ", type =" + type + "device-entry::success");
}
+ private boolean lastWakeupFromPowerButtonWithinHapticThreshold() {
+ final boolean lastWakeupFromPowerButton = mWakefulnessLifecycle.getLastWakeReason()
+ == PowerManager.WAKE_REASON_POWER_BUTTON;
+ return lastWakeupFromPowerButton
+ && mWakefulnessLifecycle.getLastWakeTime() != UNKNOWN_LAST_WAKE_TIME
+ && mSystemClock.uptimeMillis() - mWakefulnessLifecycle.getLastWakeTime()
+ < RECENT_POWER_BUTTON_PRESS_THRESHOLD_MS;
+ }
+
private void vibrateError(BiometricSourceType type) {
mVibratorHelper.vibrateAuthError(
getClass().getSimpleName() + ", type =" + type + "device-entry::error");
@@ -798,7 +824,7 @@
if (mUpdateMonitor.isUdfpsSupported()) {
pw.print(" mNumConsecutiveFpFailures="); pw.println(mNumConsecutiveFpFailures);
pw.print(" time since last failure=");
- pw.println(SystemClock.uptimeMillis() - mLastFpFailureUptimeMillis);
+ pw.println(mSystemClock.uptimeMillis() - mLastFpFailureUptimeMillis);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index 22ebcab..4b56594 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -4247,8 +4247,7 @@
@Override
public void onDozeAmountChanged(float linear, float eased) {
- if (mFeatureFlags.isEnabled(Flags.LOCKSCREEN_ANIMATIONS)
- && !mFeatureFlags.isEnabled(Flags.LIGHT_REVEAL_MIGRATION)
+ if (!mFeatureFlags.isEnabled(Flags.LIGHT_REVEAL_MIGRATION)
&& !(mLightRevealScrim.getRevealEffect() instanceof CircleReveal)) {
mLightRevealScrim.setRevealAmount(1f - linear);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index de7b152..0446cef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -44,10 +44,9 @@
import com.android.systemui.doze.AlwaysOnDisplayPolicy;
import com.android.systemui.doze.DozeScreenState;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DevicePostureController;
import com.android.systemui.tuner.TunerService;
@@ -82,7 +81,6 @@
private final AlwaysOnDisplayPolicy mAlwaysOnPolicy;
private final Resources mResources;
private final BatteryController mBatteryController;
- private final FeatureFlags mFeatureFlags;
private final ScreenOffAnimationController mScreenOffAnimationController;
private final FoldAodAnimationController mFoldAodAnimationController;
private final UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
@@ -125,7 +123,6 @@
BatteryController batteryController,
TunerService tunerService,
DumpManager dumpManager,
- FeatureFlags featureFlags,
ScreenOffAnimationController screenOffAnimationController,
Optional<SysUIUnfoldComponent> sysUiUnfoldComponent,
UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
@@ -141,7 +138,6 @@
mControlScreenOffAnimation = !getDisplayNeedsBlanking();
mPowerManager = powerManager;
mPowerManager.setDozeAfterScreenOff(!mControlScreenOffAnimation);
- mFeatureFlags = featureFlags;
mScreenOffAnimationController = screenOffAnimationController;
mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
@@ -162,6 +158,13 @@
SettingsObserver quickPickupSettingsObserver = new SettingsObserver(context, handler);
quickPickupSettingsObserver.observe();
+
+ batteryController.addCallback(new BatteryStateChangeCallback() {
+ @Override
+ public void onPowerSaveChanged(boolean isPowerSave) {
+ dispatchAlwaysOnEvent();
+ }
+ });
}
private void updateQuickPickupEnabled() {
@@ -300,13 +303,10 @@
/**
* Whether we're capable of controlling the screen off animation if we want to. This isn't
- * possible if AOD isn't even enabled or if the flag is disabled, or if the display needs
- * blanking.
+ * possible if AOD isn't even enabled or if the display needs blanking.
*/
public boolean canControlUnlockedScreenOff() {
- return getAlwaysOn()
- && mFeatureFlags.isEnabled(Flags.LOCKSCREEN_ANIMATIONS)
- && !getDisplayNeedsBlanking();
+ return getAlwaysOn() && !getDisplayNeedsBlanking();
}
/**
@@ -424,9 +424,7 @@
updateControlScreenOff();
}
- for (Callback callback : mCallbacks) {
- callback.onAlwaysOnChange();
- }
+ dispatchAlwaysOnEvent();
mScreenOffAnimationController.onAlwaysOnChanged(getAlwaysOn());
}
@@ -463,6 +461,12 @@
pw.print("isQuickPickupEnabled(): "); pw.println(isQuickPickupEnabled());
}
+ private void dispatchAlwaysOnEvent() {
+ for (Callback callback : mCallbacks) {
+ callback.onAlwaysOnChange();
+ }
+ }
+
private boolean getPostureSpecificBool(
int[] postureMapping,
boolean defaultSensorBool,
@@ -477,7 +481,8 @@
return bool;
}
- interface Callback {
+ /** Callbacks for doze parameter related information */
+ public interface Callback {
/**
* Invoked when the value of getAlwaysOn may have changed.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 000fe14..f08de85 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -17,6 +17,8 @@
package com.android.systemui.statusbar.phone;
import static com.android.keyguard.KeyguardSecurityModel.SecurityMode;
+import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN;
+import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE;
import static com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import android.content.Context;
@@ -64,14 +66,6 @@
private static final String TAG = "PrimaryKeyguardBouncer";
static final long BOUNCER_FACE_DELAY = 1200;
public static final float ALPHA_EXPANSION_THRESHOLD = 0.95f;
- /**
- * Values for the bouncer expansion represented as the panel expansion.
- * Panel expansion 1f = panel fully showing = bouncer fully hidden
- * Panel expansion 0f = panel fully hiding = bouncer fully showing
- */
- public static final float EXPANSION_HIDDEN = 1f;
- public static final float EXPANSION_VISIBLE = 0f;
-
protected final Context mContext;
protected final ViewMediatorCallback mCallback;
protected final ViewGroup mContainer;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
index b965ac9..ff1b31d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
@@ -30,6 +30,9 @@
import com.android.systemui.statusbar.NotificationLockscreenUserManager
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm
+import com.android.systemui.statusbar.policy.DevicePostureController
+import com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_UNKNOWN
+import com.android.systemui.statusbar.policy.DevicePostureController.DevicePostureInt
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.tuner.TunerService
import java.io.PrintWriter
@@ -40,11 +43,19 @@
private val mKeyguardStateController: KeyguardStateController
private val statusBarStateController: StatusBarStateController
+ private val devicePostureController: DevicePostureController
@BypassOverride private val bypassOverride: Int
private var hasFaceFeature: Boolean
+ @DevicePostureInt private val configFaceAuthSupportedPosture: Int
+ @DevicePostureInt private var postureState: Int = DEVICE_POSTURE_UNKNOWN
private var pendingUnlock: PendingUnlock? = null
private val listeners = mutableListOf<OnBypassStateChangedListener>()
-
+ private val postureCallback = DevicePostureController.Callback { posture ->
+ if (postureState != posture) {
+ postureState = posture
+ notifyListeners()
+ }
+ }
private val faceAuthEnabledChangedCallback = object : KeyguardStateController.Callback {
override fun onFaceAuthEnabledChanged() = notifyListeners()
}
@@ -86,7 +97,8 @@
FACE_UNLOCK_BYPASS_NEVER -> false
else -> field
}
- return enabled && mKeyguardStateController.isFaceAuthEnabled
+ return enabled && mKeyguardStateController.isFaceAuthEnabled &&
+ isPostureAllowedForFaceAuth()
}
private set(value) {
field = value
@@ -106,18 +118,31 @@
lockscreenUserManager: NotificationLockscreenUserManager,
keyguardStateController: KeyguardStateController,
shadeExpansionStateManager: ShadeExpansionStateManager,
+ devicePostureController: DevicePostureController,
dumpManager: DumpManager
) {
this.mKeyguardStateController = keyguardStateController
this.statusBarStateController = statusBarStateController
+ this.devicePostureController = devicePostureController
bypassOverride = context.resources.getInteger(R.integer.config_face_unlock_bypass_override)
+ configFaceAuthSupportedPosture =
+ context.resources.getInteger(R.integer.config_face_auth_supported_posture)
- hasFaceFeature = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FACE)
+ hasFaceFeature = context.packageManager.hasSystemFeature(PackageManager.FEATURE_FACE)
if (!hasFaceFeature) {
return
}
+ if (configFaceAuthSupportedPosture != DEVICE_POSTURE_UNKNOWN) {
+ devicePostureController.addCallback { posture ->
+ if (postureState != posture) {
+ postureState = posture
+ notifyListeners()
+ }
+ }
+ }
+
dumpManager.registerDumpable("KeyguardBypassController", this)
statusBarStateController.addCallback(object : StatusBarStateController.StateListener {
override fun onStateChanged(newState: Int) {
@@ -203,6 +228,13 @@
pendingUnlock = null
}
+ fun isPostureAllowedForFaceAuth(): Boolean {
+ return when (configFaceAuthSupportedPosture) {
+ DEVICE_POSTURE_UNKNOWN -> true
+ else -> (postureState == configFaceAuthSupportedPosture)
+ }
+ }
+
override fun dump(pw: PrintWriter, args: Array<out String>) {
pw.println("KeyguardBypassController:")
if (pendingUnlock != null) {
@@ -219,6 +251,7 @@
pw.println(" launchingAffordance: $launchingAffordance")
pw.println(" qSExpanded: $qsExpanded")
pw.println(" hasFaceFeature: $hasFaceFeature")
+ pw.println(" postureState: $postureState")
}
/** Registers a listener for bypass state changes. */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index ee8b861..f784723 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -53,6 +53,7 @@
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dock.DockManager;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
+import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants;
import com.android.systemui.scrim.ScrimView;
import com.android.systemui.shade.NotificationPanelViewController;
import com.android.systemui.statusbar.notification.stack.ViewState;
@@ -147,7 +148,7 @@
* 0, the bouncer is visible.
*/
@FloatRange(from = 0, to = 1)
- private float mBouncerHiddenFraction = KeyguardBouncer.EXPANSION_HIDDEN;
+ private float mBouncerHiddenFraction = KeyguardBouncerConstants.EXPANSION_HIDDEN;
/**
* Set whether an unocclusion animation is currently running on the notification panel. Used
@@ -810,7 +811,7 @@
}
if (mState == ScrimState.DREAMING
- && mBouncerHiddenFraction != KeyguardBouncer.EXPANSION_HIDDEN) {
+ && mBouncerHiddenFraction != KeyguardBouncerConstants.EXPANSION_HIDDEN) {
final float interpolatedFraction =
BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(
mBouncerHiddenFraction);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index 1a14a036..24ad55d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -79,12 +79,30 @@
/** Refresh the state of an IconManager by recreating the views */
void refreshIconGroup(IconManager iconManager);
- /** */
+
+ /**
+ * Adds or updates an icon for a given slot for a **tile service icon**.
+ *
+ * TODO(b/265307726): Merge with {@link #setIcon(String, StatusBarIcon)} or make this method
+ * much more clearly distinct from that method.
+ */
void setExternalIcon(String slot);
- /** */
+
+ /**
+ * Adds or updates an icon for the given slot for **internal system icons**.
+ *
+ * TODO(b/265307726): Rename to `setInternalIcon`, or merge this appropriately with the
+ * {@link #setIcon(String, StatusBarIcon)} method.
+ */
void setIcon(String slot, int resourceId, CharSequence contentDescription);
- /** */
+
+ /**
+ * Adds or updates an icon for the given slot for an **externally-provided icon**.
+ *
+ * TODO(b/265307726): Rename to `setExternalIcon` or something similar.
+ */
void setIcon(String slot, StatusBarIcon icon);
+
/** */
void setWifiIcon(String slot, WifiIconState state);
@@ -133,9 +151,17 @@
* TAG_PRIMARY to refer to the first icon at a given slot.
*/
void removeIcon(String slot, int tag);
+
/** */
void removeAllIconsForSlot(String slot);
+ /**
+ * Removes all the icons for the given slot.
+ *
+ * Only use this for icons that have come from **an external process**.
+ */
+ void removeAllIconsForExternalSlot(String slot);
+
// TODO: See if we can rename this tunable name.
String ICON_HIDE_LIST = "icon_blacklist";
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
index 9fbe6cb..416bc71 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
@@ -28,6 +28,8 @@
import android.util.Log;
import android.view.ViewGroup;
+import androidx.annotation.VisibleForTesting;
+
import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
@@ -63,6 +65,10 @@
ConfigurationListener, Dumpable, CommandQueue.Callbacks, StatusBarIconController, DemoMode {
private static final String TAG = "StatusBarIconController";
+ // Use this suffix to prevent external icon slot names from unintentionally overriding our
+ // internal, system-level slot names. See b/255428281.
+ @VisibleForTesting
+ protected static final String EXTERNAL_SLOT_SUFFIX = "__external";
private final StatusBarIconList mStatusBarIconList;
private final ArrayList<IconManager> mIconGroups = new ArrayList<>();
@@ -346,21 +352,26 @@
@Override
public void setExternalIcon(String slot) {
- int viewIndex = mStatusBarIconList.getViewIndex(slot, 0);
+ String slotName = createExternalSlotName(slot);
+ int viewIndex = mStatusBarIconList.getViewIndex(slotName, 0);
int height = mContext.getResources().getDimensionPixelSize(
R.dimen.status_bar_icon_drawing_size);
mIconGroups.forEach(l -> l.onIconExternal(viewIndex, height));
}
- //TODO: remove this (used in command queue and for 3rd party tiles?)
+ // Override for *both* CommandQueue.Callbacks AND StatusBarIconController.
+ // TODO(b/265307726): Pull out the CommandQueue callbacks into a member variable to
+ // differentiate between those callback methods and StatusBarIconController methods.
+ @Override
public void setIcon(String slot, StatusBarIcon icon) {
+ String slotName = createExternalSlotName(slot);
if (icon == null) {
- removeAllIconsForSlot(slot);
+ removeAllIconsForSlot(slotName);
return;
}
StatusBarIconHolder holder = StatusBarIconHolder.fromIcon(icon);
- setIcon(slot, holder);
+ setIcon(slotName, holder);
}
private void setIcon(String slot, @NonNull StatusBarIconHolder holder) {
@@ -406,10 +417,12 @@
}
}
- /** */
+ // CommandQueue.Callbacks override
+ // TODO(b/265307726): Pull out the CommandQueue callbacks into a member variable to
+ // differentiate between those callback methods and StatusBarIconController methods.
@Override
public void removeIcon(String slot) {
- removeAllIconsForSlot(slot);
+ removeAllIconsForExternalSlot(slot);
}
/** */
@@ -423,6 +436,11 @@
mIconGroups.forEach(l -> l.onRemoveIcon(viewIndex));
}
+ @Override
+ public void removeAllIconsForExternalSlot(String slotName) {
+ removeAllIconsForSlot(createExternalSlotName(slotName));
+ }
+
/** */
@Override
public void removeAllIconsForSlot(String slotName) {
@@ -506,4 +524,12 @@
public void onDensityOrFontScaleChanged() {
refreshIconGroups();
}
+
+ private String createExternalSlotName(String slot) {
+ if (slot.endsWith(EXTERNAL_SLOT_SUFFIX)) {
+ return slot;
+ } else {
+ return slot + EXTERNAL_SLOT_SUFFIX;
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 61ddf8c..003b020 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -18,6 +18,7 @@
import static android.view.WindowInsets.Type.navigationBars;
+import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN;
import static com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING;
@@ -36,7 +37,8 @@
import android.view.ViewGroup;
import android.view.ViewRootImpl;
import android.view.WindowManagerGlobal;
-import android.window.OnBackInvokedCallback;
+import android.window.BackEvent;
+import android.window.OnBackAnimationCallback;
import android.window.OnBackInvokedDispatcher;
import androidx.annotation.NonNull;
@@ -184,8 +186,7 @@
isVisible && mDreamOverlayStateController.isOverlayActive());
if (!isVisible) {
- mCentralSurfaces.setPrimaryBouncerHiddenFraction(
- KeyguardBouncer.EXPANSION_HIDDEN);
+ mCentralSurfaces.setPrimaryBouncerHiddenFraction(EXPANSION_HIDDEN);
}
/* Register predictive back callback when keyguard becomes visible, and unregister
@@ -198,11 +199,38 @@
}
};
- private final OnBackInvokedCallback mOnBackInvokedCallback = () -> {
- if (DEBUG) {
- Log.d(TAG, "onBackInvokedCallback() called, invoking onBackPressed()");
+ private final OnBackAnimationCallback mOnBackInvokedCallback = new OnBackAnimationCallback() {
+ @Override
+ public void onBackInvoked() {
+ if (DEBUG) {
+ Log.d(TAG, "onBackInvokedCallback() called, invoking onBackPressed()");
+ }
+ onBackPressed();
+ if (shouldPlayBackAnimation()) {
+ mPrimaryBouncerView.getDelegate().getBackCallback().onBackInvoked();
+ }
}
- onBackPressed();
+
+ @Override
+ public void onBackProgressed(BackEvent event) {
+ if (shouldPlayBackAnimation()) {
+ mPrimaryBouncerView.getDelegate().getBackCallback().onBackProgressed(event);
+ }
+ }
+
+ @Override
+ public void onBackCancelled() {
+ if (shouldPlayBackAnimation()) {
+ mPrimaryBouncerView.getDelegate().getBackCallback().onBackCancelled();
+ }
+ }
+
+ @Override
+ public void onBackStarted(BackEvent event) {
+ if (shouldPlayBackAnimation()) {
+ mPrimaryBouncerView.getDelegate().getBackCallback().onBackStarted(event);
+ }
+ }
};
private boolean mIsBackCallbackRegistered = false;
@@ -256,6 +284,7 @@
private boolean mIsModernBouncerEnabled;
private boolean mIsModernAlternateBouncerEnabled;
private boolean mIsUnoccludeTransitionFlagEnabled;
+ private boolean mIsBackAnimationEnabled;
private OnDismissAction mAfterKeyguardGoneAction;
private Runnable mKeyguardGoneCancelAction;
@@ -337,6 +366,8 @@
mIsModernAlternateBouncerEnabled = featureFlags.isEnabled(Flags.MODERN_ALTERNATE_BOUNCER);
mAlternateBouncerInteractor = alternateBouncerInteractor;
mIsUnoccludeTransitionFlagEnabled = featureFlags.isEnabled(Flags.UNOCCLUSION_TRANSITION);
+ mIsBackAnimationEnabled =
+ featureFlags.isEnabled(Flags.WM_ENABLE_PREDICTIVE_BACK_BOUNCER_ANIM);
}
@Override
@@ -472,6 +503,11 @@
}
}
+ private boolean shouldPlayBackAnimation() {
+ // Suppress back animation when bouncer shouldn't be dismissed on back invocation.
+ return !needsFullscreenBouncer() && mIsBackAnimationEnabled;
+ }
+
@Override
public void onDensityOrFontScaleChanged() {
hideBouncer(true /* destroyView */);
@@ -485,7 +521,7 @@
|| mNotificationPanelViewController.isExpanding());
final boolean isUserTrackingStarted =
- event.getFraction() != KeyguardBouncer.EXPANSION_HIDDEN && event.getTracking();
+ event.getFraction() != EXPANSION_HIDDEN && event.getTracking();
return mKeyguardStateController.isShowing()
&& !primaryBouncerIsOrWillBeShowing()
@@ -535,9 +571,9 @@
}
} else {
if (mPrimaryBouncer != null) {
- mPrimaryBouncer.setExpansion(KeyguardBouncer.EXPANSION_HIDDEN);
+ mPrimaryBouncer.setExpansion(EXPANSION_HIDDEN);
} else {
- mPrimaryBouncerInteractor.setPanelExpansion(KeyguardBouncer.EXPANSION_HIDDEN);
+ mPrimaryBouncerInteractor.setPanelExpansion(EXPANSION_HIDDEN);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemBarAttributesListener.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemBarAttributesListener.kt
index 08599c2..fbe374c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemBarAttributesListener.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemBarAttributesListener.kt
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.phone
+import android.view.InsetsFlags
+import android.view.ViewDebug
import android.view.WindowInsets.Type.InsetsType
import android.view.WindowInsetsController.Appearance
import android.view.WindowInsetsController.Behavior
@@ -148,4 +150,20 @@
) {
val letterboxesArray = letterboxes.toTypedArray()
val appearanceRegionsArray = appearanceRegions.toTypedArray()
+ override fun toString(): String {
+ val appearanceToString =
+ ViewDebug.flagsToString(InsetsFlags::class.java, "appearance", appearance)
+ return """SystemBarAttributesParams(
+ displayId=$displayId,
+ appearance=$appearanceToString,
+ appearanceRegions=$appearanceRegions,
+ navbarColorManagedByIme=$navbarColorManagedByIme,
+ behavior=$behavior,
+ requestedVisibleTypes=$requestedVisibleTypes,
+ packageName='$packageName',
+ letterboxes=$letterboxes,
+ letterboxesArray=${letterboxesArray.contentToString()},
+ appearanceRegionsArray=${appearanceRegionsArray.contentToString()}
+ )""".trimMargin()
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/ResolvedNetworkType.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/ResolvedNetworkType.kt
index 5960387..5562e73 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/ResolvedNetworkType.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/ResolvedNetworkType.kt
@@ -17,6 +17,8 @@
package com.android.systemui.statusbar.pipeline.mobile.data.model
import android.telephony.Annotation.NetworkType
+import com.android.settingslib.SignalIcon
+import com.android.settingslib.mobile.TelephonyIcons
import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
/**
@@ -38,4 +40,12 @@
data class OverrideNetworkType(
override val lookupKey: String,
) : ResolvedNetworkType
+
+ /** Represents the carrier merged network. See [CarrierMergedConnectionRepository]. */
+ object CarrierMergedNetworkType : ResolvedNetworkType {
+ // Effectively unused since [iconGroupOverride] is used instead.
+ override val lookupKey: String = "cwf"
+
+ val iconGroupOverride: SignalIcon.MobileIconGroup = TelephonyIcons.CARRIER_MERGED_WIFI
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionRepository.kt
index d04996b..6187f64 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionRepository.kt
@@ -22,7 +22,6 @@
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
-import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
/**
@@ -50,7 +49,7 @@
* A flow that aggregates all necessary callbacks from [TelephonyCallback] into a single
* listener + model.
*/
- val connectionInfo: Flow<MobileConnectionModel>
+ val connectionInfo: StateFlow<MobileConnectionModel>
/** The total number of levels. Used with [SignalDrawable]. */
val numberOfLevels: StateFlow<Int>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt
index 0e164e7..22aca0a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt
@@ -39,7 +39,11 @@
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel.Mobile
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel.MobileDisabled
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.CarrierMergedConnectionRepository.Companion.createCarrierMergedConnectionModel
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Factory.Companion.MOBILE_CONNECTION_BUFFER_SIZE
import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
+import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoModeWifiDataSource
+import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.FakeWifiEventModel
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -60,15 +64,19 @@
class DemoMobileConnectionsRepository
@Inject
constructor(
- private val dataSource: DemoModeMobileConnectionDataSource,
+ private val mobileDataSource: DemoModeMobileConnectionDataSource,
+ private val wifiDataSource: DemoModeWifiDataSource,
@Application private val scope: CoroutineScope,
context: Context,
private val logFactory: TableLogBufferFactory,
) : MobileConnectionsRepository {
- private var demoCommandJob: Job? = null
+ private var mobileDemoCommandJob: Job? = null
+ private var wifiDemoCommandJob: Job? = null
- private var connectionRepoCache = mutableMapOf<Int, DemoMobileConnectionRepository>()
+ private var carrierMergedSubId: Int? = null
+
+ private var connectionRepoCache = mutableMapOf<Int, CacheContainer>()
private val subscriptionInfoCache = mutableMapOf<Int, SubscriptionModel>()
val demoModeFinishedEvent = MutableSharedFlow<Unit>(extraBufferCapacity = 1)
@@ -144,52 +152,83 @@
override val defaultMobileNetworkConnectivity = MutableStateFlow(MobileConnectivityModel())
override fun getRepoForSubId(subId: Int): DemoMobileConnectionRepository {
- return connectionRepoCache[subId]
- ?: createDemoMobileConnectionRepo(subId).also { connectionRepoCache[subId] = it }
+ val current = connectionRepoCache[subId]?.repo
+ if (current != null) {
+ return current
+ }
+
+ val new = createDemoMobileConnectionRepo(subId)
+ connectionRepoCache[subId] = new
+ return new.repo
}
- private fun createDemoMobileConnectionRepo(subId: Int): DemoMobileConnectionRepository {
- val tableLogBuffer = logFactory.create("DemoMobileConnectionLog [$subId]", 100)
+ private fun createDemoMobileConnectionRepo(subId: Int): CacheContainer {
+ val tableLogBuffer =
+ logFactory.getOrCreate(
+ "DemoMobileConnectionLog [$subId]",
+ MOBILE_CONNECTION_BUFFER_SIZE,
+ )
- return DemoMobileConnectionRepository(
- subId,
- tableLogBuffer,
- )
+ val repo =
+ DemoMobileConnectionRepository(
+ subId,
+ tableLogBuffer,
+ )
+ return CacheContainer(repo, lastMobileState = null)
}
override val globalMobileDataSettingChangedEvent = MutableStateFlow(Unit)
fun startProcessingCommands() {
- demoCommandJob =
+ mobileDemoCommandJob =
scope.launch {
- dataSource.mobileEvents.filterNotNull().collect { event -> processEvent(event) }
+ mobileDataSource.mobileEvents.filterNotNull().collect { event ->
+ processMobileEvent(event)
+ }
+ }
+ wifiDemoCommandJob =
+ scope.launch {
+ wifiDataSource.wifiEvents.filterNotNull().collect { event ->
+ processWifiEvent(event)
+ }
}
}
fun stopProcessingCommands() {
- demoCommandJob?.cancel()
+ mobileDemoCommandJob?.cancel()
+ wifiDemoCommandJob?.cancel()
_subscriptions.value = listOf()
connectionRepoCache.clear()
subscriptionInfoCache.clear()
}
- private fun processEvent(event: FakeNetworkEventModel) {
+ private fun processMobileEvent(event: FakeNetworkEventModel) {
when (event) {
is Mobile -> {
processEnabledMobileState(event)
}
is MobileDisabled -> {
- processDisabledMobileState(event)
+ maybeRemoveSubscription(event.subId)
}
}
}
+ private fun processWifiEvent(event: FakeWifiEventModel) {
+ when (event) {
+ is FakeWifiEventModel.WifiDisabled -> disableCarrierMerged()
+ is FakeWifiEventModel.Wifi -> disableCarrierMerged()
+ is FakeWifiEventModel.CarrierMerged -> processCarrierMergedWifiState(event)
+ }
+ }
+
private fun processEnabledMobileState(state: Mobile) {
// get or create the connection repo, and set its values
val subId = state.subId ?: DEFAULT_SUB_ID
maybeCreateSubscription(subId)
val connection = getRepoForSubId(subId)
+ connectionRepoCache[subId]?.lastMobileState = state
+
// This is always true here, because we split out disabled states at the data-source level
connection.dataEnabled.value = true
connection.networkName.value = NetworkNameModel.Derived(state.name)
@@ -198,14 +237,36 @@
connection.connectionInfo.value = state.toMobileConnectionModel()
}
- private fun processDisabledMobileState(state: MobileDisabled) {
+ private fun processCarrierMergedWifiState(event: FakeWifiEventModel.CarrierMerged) {
+ // The new carrier merged connection is for a different sub ID, so disable carrier merged
+ // for the current (now old) sub
+ if (carrierMergedSubId != event.subscriptionId) {
+ disableCarrierMerged()
+ }
+
+ // get or create the connection repo, and set its values
+ val subId = event.subscriptionId
+ maybeCreateSubscription(subId)
+ carrierMergedSubId = subId
+
+ val connection = getRepoForSubId(subId)
+ // This is always true here, because we split out disabled states at the data-source level
+ connection.dataEnabled.value = true
+ connection.networkName.value = NetworkNameModel.Derived(CARRIER_MERGED_NAME)
+ connection.numberOfLevels.value = event.numberOfLevels
+ connection.cdmaRoaming.value = false
+ connection.connectionInfo.value = event.toMobileConnectionModel()
+ Log.e("CCS", "output connection info = ${connection.connectionInfo.value}")
+ }
+
+ private fun maybeRemoveSubscription(subId: Int?) {
if (_subscriptions.value.isEmpty()) {
// Nothing to do here
return
}
- val subId =
- state.subId
+ val finalSubId =
+ subId
?: run {
// For sake of usability, we can allow for no subId arg if there is only one
// subscription
@@ -223,7 +284,21 @@
_subscriptions.value[0].subscriptionId
}
- removeSubscription(subId)
+ removeSubscription(finalSubId)
+ }
+
+ private fun disableCarrierMerged() {
+ val currentCarrierMergedSubId = carrierMergedSubId ?: return
+
+ // If this sub ID was previously not carrier merged, we should reset it to its previous
+ // connection.
+ val lastMobileState = connectionRepoCache[carrierMergedSubId]?.lastMobileState
+ if (lastMobileState != null) {
+ processEnabledMobileState(lastMobileState)
+ } else {
+ // Otherwise, just remove the subscription entirely
+ removeSubscription(currentCarrierMergedSubId)
+ }
}
private fun removeSubscription(subId: Int) {
@@ -251,6 +326,10 @@
)
}
+ private fun FakeWifiEventModel.CarrierMerged.toMobileConnectionModel(): MobileConnectionModel {
+ return createCarrierMergedConnectionModel(this.level)
+ }
+
private fun SignalIcon.MobileIconGroup?.toResolvedNetworkType(): ResolvedNetworkType {
val key = mobileMappingsReverseLookup.value[this] ?: "dis"
return DefaultNetworkType(key)
@@ -260,9 +339,17 @@
private const val TAG = "DemoMobileConnectionsRepo"
private const val DEFAULT_SUB_ID = 1
+
+ private const val CARRIER_MERGED_NAME = "Carrier Merged Network"
}
}
+class CacheContainer(
+ var repo: DemoMobileConnectionRepository,
+ /** The last received [Mobile] event. Used when switching from carrier merged back to mobile. */
+ var lastMobileState: Mobile?,
+)
+
class DemoMobileConnectionRepository(
override val subId: Int,
override val tableLogBuffer: TableLogBuffer,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt
new file mode 100644
index 0000000..c783b12
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.mobile.data.repository.prod
+
+import android.util.Log
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
+import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
+import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
+import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS
+import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
+import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel
+import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.stateIn
+
+/**
+ * A repository implementation for a carrier merged (aka VCN) network. A carrier merged network is
+ * delivered to SysUI as a wifi network (see [WifiNetworkModel.CarrierMerged], but is visually
+ * displayed as a mobile network triangle.
+ *
+ * See [android.net.wifi.WifiInfo.isCarrierMerged] for more information.
+ *
+ * See [MobileConnectionRepositoryImpl] for a repository implementation of a typical mobile
+ * connection.
+ */
+class CarrierMergedConnectionRepository(
+ override val subId: Int,
+ override val tableLogBuffer: TableLogBuffer,
+ defaultNetworkName: NetworkNameModel,
+ @Application private val scope: CoroutineScope,
+ val wifiRepository: WifiRepository,
+) : MobileConnectionRepository {
+
+ /**
+ * Outputs the carrier merged network to use, or null if we don't have a valid carrier merged
+ * network.
+ */
+ private val network: Flow<WifiNetworkModel.CarrierMerged?> =
+ combine(
+ wifiRepository.isWifiEnabled,
+ wifiRepository.isWifiDefault,
+ wifiRepository.wifiNetwork,
+ ) { isEnabled, isDefault, network ->
+ when {
+ !isEnabled -> null
+ !isDefault -> null
+ network !is WifiNetworkModel.CarrierMerged -> null
+ network.subscriptionId != subId -> {
+ Log.w(
+ TAG,
+ "Connection repo subId=$subId " +
+ "does not equal wifi repo subId=${network.subscriptionId}; " +
+ "not showing carrier merged"
+ )
+ null
+ }
+ else -> network
+ }
+ }
+
+ override val connectionInfo: StateFlow<MobileConnectionModel> =
+ network
+ .map { it.toMobileConnectionModel() }
+ .stateIn(scope, SharingStarted.WhileSubscribed(), MobileConnectionModel())
+
+ // TODO(b/238425913): Add logging to this class.
+ // TODO(b/238425913): Make sure SignalStrength.getEmptyState is used when appropriate.
+
+ // Carrier merged is never roaming.
+ override val cdmaRoaming: StateFlow<Boolean> = MutableStateFlow(false).asStateFlow()
+
+ // TODO(b/238425913): Fetch the carrier merged network name.
+ override val networkName: StateFlow<NetworkNameModel> =
+ flowOf(defaultNetworkName)
+ .stateIn(scope, SharingStarted.WhileSubscribed(), defaultNetworkName)
+
+ override val numberOfLevels: StateFlow<Int> =
+ wifiRepository.wifiNetwork
+ .map {
+ if (it is WifiNetworkModel.CarrierMerged) {
+ it.numberOfLevels
+ } else {
+ DEFAULT_NUM_LEVELS
+ }
+ }
+ .stateIn(scope, SharingStarted.WhileSubscribed(), DEFAULT_NUM_LEVELS)
+
+ override val dataEnabled: StateFlow<Boolean> = wifiRepository.isWifiEnabled
+
+ private fun WifiNetworkModel.CarrierMerged?.toMobileConnectionModel(): MobileConnectionModel {
+ if (this == null) {
+ return MobileConnectionModel()
+ }
+
+ return createCarrierMergedConnectionModel(level)
+ }
+
+ companion object {
+ /**
+ * Creates an instance of [MobileConnectionModel] that represents a carrier merged network
+ * with the given [level].
+ */
+ fun createCarrierMergedConnectionModel(level: Int): MobileConnectionModel {
+ return MobileConnectionModel(
+ primaryLevel = level,
+ cdmaLevel = level,
+ // A [WifiNetworkModel.CarrierMerged] instance is always connected.
+ // (A [WifiNetworkModel.Inactive] represents a disconnected network.)
+ dataConnectionState = DataConnectionState.Connected,
+ // TODO(b/238425913): This should come from [WifiRepository.wifiActivity].
+ dataActivityDirection =
+ DataActivityModel(
+ hasActivityIn = false,
+ hasActivityOut = false,
+ ),
+ resolvedNetworkType = ResolvedNetworkType.CarrierMergedNetworkType,
+ // Carrier merged is never roaming
+ isRoaming = false,
+
+ // TODO(b/238425913): Verify that these fields never change for carrier merged.
+ isEmergencyOnly = false,
+ operatorAlphaShort = null,
+ isInService = true,
+ isGsm = false,
+ carrierNetworkChangeActive = false,
+ )
+ }
+ }
+
+ @SysUISingleton
+ class Factory
+ @Inject
+ constructor(
+ @Application private val scope: CoroutineScope,
+ private val wifiRepository: WifiRepository,
+ ) {
+ fun build(
+ subId: Int,
+ mobileLogger: TableLogBuffer,
+ defaultNetworkName: NetworkNameModel,
+ ): MobileConnectionRepository {
+ return CarrierMergedConnectionRepository(
+ subId,
+ mobileLogger,
+ defaultNetworkName,
+ scope,
+ wifiRepository,
+ )
+ }
+ }
+}
+
+private const val TAG = "CarrierMergedConnectionRepository"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt
new file mode 100644
index 0000000..0f30ae2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.mobile.data.repository.prod
+
+import androidx.annotation.VisibleForTesting
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.log.table.TableLogBufferFactory
+import com.android.systemui.log.table.logDiffsForTable
+import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.mapLatest
+import kotlinx.coroutines.flow.stateIn
+
+/**
+ * A repository that fully implements a mobile connection.
+ *
+ * This connection could either be a typical mobile connection (see [MobileConnectionRepositoryImpl]
+ * or a carrier merged connection (see [CarrierMergedConnectionRepository]). This repository
+ * switches between the two types of connections based on whether the connection is currently
+ * carrier merged (see [setIsCarrierMerged]).
+ */
+@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
+@OptIn(ExperimentalCoroutinesApi::class)
+class FullMobileConnectionRepository(
+ override val subId: Int,
+ startingIsCarrierMerged: Boolean,
+ override val tableLogBuffer: TableLogBuffer,
+ private val defaultNetworkName: NetworkNameModel,
+ private val networkNameSeparator: String,
+ private val globalMobileDataSettingChangedEvent: Flow<Unit>,
+ @Application scope: CoroutineScope,
+ private val mobileRepoFactory: MobileConnectionRepositoryImpl.Factory,
+ private val carrierMergedRepoFactory: CarrierMergedConnectionRepository.Factory,
+) : MobileConnectionRepository {
+ /**
+ * Sets whether this connection is a typical mobile connection or a carrier merged connection.
+ */
+ fun setIsCarrierMerged(isCarrierMerged: Boolean) {
+ _isCarrierMerged.value = isCarrierMerged
+ }
+
+ /**
+ * Returns true if this repo is currently for a carrier merged connection and false otherwise.
+ */
+ @VisibleForTesting fun getIsCarrierMerged() = _isCarrierMerged.value
+
+ private val _isCarrierMerged = MutableStateFlow(startingIsCarrierMerged)
+ private val isCarrierMerged: StateFlow<Boolean> =
+ _isCarrierMerged
+ .logDiffsForTable(
+ tableLogBuffer,
+ columnPrefix = "",
+ columnName = "isCarrierMerged",
+ initialValue = startingIsCarrierMerged,
+ )
+ .stateIn(scope, SharingStarted.WhileSubscribed(), startingIsCarrierMerged)
+
+ private val mobileRepo: MobileConnectionRepository by lazy {
+ mobileRepoFactory.build(
+ subId,
+ tableLogBuffer,
+ defaultNetworkName,
+ networkNameSeparator,
+ globalMobileDataSettingChangedEvent,
+ )
+ }
+
+ private val carrierMergedRepo: MobileConnectionRepository by lazy {
+ carrierMergedRepoFactory.build(subId, tableLogBuffer, defaultNetworkName)
+ }
+
+ @VisibleForTesting
+ internal val activeRepo: StateFlow<MobileConnectionRepository> = run {
+ val initial =
+ if (startingIsCarrierMerged) {
+ carrierMergedRepo
+ } else {
+ mobileRepo
+ }
+
+ this.isCarrierMerged
+ .mapLatest { isCarrierMerged ->
+ if (isCarrierMerged) {
+ carrierMergedRepo
+ } else {
+ mobileRepo
+ }
+ }
+ .stateIn(scope, SharingStarted.WhileSubscribed(), initial)
+ }
+
+ override val cdmaRoaming =
+ activeRepo
+ .flatMapLatest { it.cdmaRoaming }
+ .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.cdmaRoaming.value)
+
+ override val connectionInfo =
+ activeRepo
+ .flatMapLatest { it.connectionInfo }
+ .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.connectionInfo.value)
+
+ override val dataEnabled =
+ activeRepo
+ .flatMapLatest { it.dataEnabled }
+ .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.dataEnabled.value)
+
+ override val numberOfLevels =
+ activeRepo
+ .flatMapLatest { it.numberOfLevels }
+ .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.numberOfLevels.value)
+
+ override val networkName =
+ activeRepo
+ .flatMapLatest { it.networkName }
+ .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.networkName.value)
+
+ class Factory
+ @Inject
+ constructor(
+ @Application private val scope: CoroutineScope,
+ private val logFactory: TableLogBufferFactory,
+ private val mobileRepoFactory: MobileConnectionRepositoryImpl.Factory,
+ private val carrierMergedRepoFactory: CarrierMergedConnectionRepository.Factory,
+ ) {
+ fun build(
+ subId: Int,
+ startingIsCarrierMerged: Boolean,
+ defaultNetworkName: NetworkNameModel,
+ networkNameSeparator: String,
+ globalMobileDataSettingChangedEvent: Flow<Unit>,
+ ): FullMobileConnectionRepository {
+ val mobileLogger =
+ logFactory.getOrCreate(tableBufferLogName(subId), MOBILE_CONNECTION_BUFFER_SIZE)
+
+ return FullMobileConnectionRepository(
+ subId,
+ startingIsCarrierMerged,
+ mobileLogger,
+ defaultNetworkName,
+ networkNameSeparator,
+ globalMobileDataSettingChangedEvent,
+ scope,
+ mobileRepoFactory,
+ carrierMergedRepoFactory,
+ )
+ }
+
+ companion object {
+ /** The buffer size to use for logging. */
+ const val MOBILE_CONNECTION_BUFFER_SIZE = 100
+
+ /** Returns a log buffer name for a mobile connection with the given [subId]. */
+ fun tableBufferLogName(subId: Int): String = "MobileConnectionLog [$subId]"
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt
index 0fa0fea..3f2ce40 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt
@@ -38,7 +38,6 @@
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.log.table.TableLogBuffer
-import com.android.systemui.log.table.TableLogBufferFactory
import com.android.systemui.log.table.logDiffsForTable
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
@@ -70,6 +69,10 @@
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
+/**
+ * A repository implementation for a typical mobile connection (as opposed to a carrier merged
+ * connection -- see [CarrierMergedConnectionRepository]).
+ */
@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
@OptIn(ExperimentalCoroutinesApi::class)
class MobileConnectionRepositoryImpl(
@@ -298,18 +301,16 @@
private val logger: ConnectivityPipelineLogger,
private val globalSettings: GlobalSettings,
private val mobileMappingsProxy: MobileMappingsProxy,
- private val logFactory: TableLogBufferFactory,
@Background private val bgDispatcher: CoroutineDispatcher,
@Application private val scope: CoroutineScope,
) {
fun build(
subId: Int,
+ mobileLogger: TableLogBuffer,
defaultNetworkName: NetworkNameModel,
networkNameSeparator: String,
globalMobileDataSettingChangedEvent: Flow<Unit>,
): MobileConnectionRepository {
- val mobileLogger = logFactory.create(tableBufferLogName(subId), 100)
-
return MobileConnectionRepositoryImpl(
context,
subId,
@@ -327,8 +328,4 @@
)
}
}
-
- companion object {
- fun tableBufferLogName(subId: Int): String = "MobileConnectionLog [$subId]"
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
index c88c700..4472e09 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
@@ -46,11 +46,12 @@
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectivityModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepository
import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.logInputChange
+import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel
+import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository
import com.android.systemui.util.settings.GlobalSettings
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
@@ -85,9 +86,14 @@
private val context: Context,
@Background private val bgDispatcher: CoroutineDispatcher,
@Application private val scope: CoroutineScope,
- private val mobileConnectionRepositoryFactory: MobileConnectionRepositoryImpl.Factory
+ // Some "wifi networks" should be rendered as a mobile connection, which is why the wifi
+ // repository is an input to the mobile repository.
+ // See [CarrierMergedConnectionRepository] for details.
+ wifiRepository: WifiRepository,
+ private val fullMobileRepoFactory: FullMobileConnectionRepository.Factory,
) : MobileConnectionsRepository {
- private var subIdRepositoryCache: MutableMap<Int, MobileConnectionRepository> = mutableMapOf()
+ private var subIdRepositoryCache: MutableMap<Int, FullMobileConnectionRepository> =
+ mutableMapOf()
private val defaultNetworkName =
NetworkNameModel.Default(
@@ -97,30 +103,43 @@
private val networkNameSeparator: String =
context.getString(R.string.status_bar_network_name_separator)
+ private val carrierMergedSubId: StateFlow<Int?> =
+ wifiRepository.wifiNetwork
+ .mapLatest {
+ if (it is WifiNetworkModel.CarrierMerged) {
+ it.subscriptionId
+ } else {
+ null
+ }
+ }
+ .distinctUntilChanged()
+ .stateIn(scope, started = SharingStarted.WhileSubscribed(), null)
+
+ private val mobileSubscriptionsChangeEvent: Flow<Unit> = conflatedCallbackFlow {
+ val callback =
+ object : SubscriptionManager.OnSubscriptionsChangedListener() {
+ override fun onSubscriptionsChanged() {
+ trySend(Unit)
+ }
+ }
+
+ subscriptionManager.addOnSubscriptionsChangedListener(
+ bgDispatcher.asExecutor(),
+ callback,
+ )
+
+ awaitClose { subscriptionManager.removeOnSubscriptionsChangedListener(callback) }
+ }
+
/**
* State flow that emits the set of mobile data subscriptions, each represented by its own
- * [SubscriptionInfo]. We probably only need the [SubscriptionInfo.getSubscriptionId] of each
- * info object, but for now we keep track of the infos themselves.
+ * [SubscriptionModel].
*/
override val subscriptions: StateFlow<List<SubscriptionModel>> =
- conflatedCallbackFlow {
- val callback =
- object : SubscriptionManager.OnSubscriptionsChangedListener() {
- override fun onSubscriptionsChanged() {
- trySend(Unit)
- }
- }
-
- subscriptionManager.addOnSubscriptionsChangedListener(
- bgDispatcher.asExecutor(),
- callback,
- )
-
- awaitClose { subscriptionManager.removeOnSubscriptionsChangedListener(callback) }
- }
+ merge(mobileSubscriptionsChangeEvent, carrierMergedSubId)
.mapLatest { fetchSubscriptionsList().map { it.toSubscriptionModel() } }
.logInputChange(logger, "onSubscriptionsChanged")
- .onEach { infos -> dropUnusedReposFromCache(infos) }
+ .onEach { infos -> updateRepos(infos) }
.stateIn(scope, started = SharingStarted.WhileSubscribed(), listOf())
/** StateFlow that keeps track of the current active mobile data subscription */
@@ -173,7 +192,7 @@
.distinctUntilChanged()
.logInputChange(logger, "defaultMobileIconGroup")
- override fun getRepoForSubId(subId: Int): MobileConnectionRepository {
+ override fun getRepoForSubId(subId: Int): FullMobileConnectionRepository {
if (!isValidSubId(subId)) {
throw IllegalArgumentException(
"subscriptionId $subId is not in the list of valid subscriptions"
@@ -251,15 +270,27 @@
@VisibleForTesting fun getSubIdRepoCache() = subIdRepositoryCache
- private fun createRepositoryForSubId(subId: Int): MobileConnectionRepository {
- return mobileConnectionRepositoryFactory.build(
+ private fun createRepositoryForSubId(subId: Int): FullMobileConnectionRepository {
+ return fullMobileRepoFactory.build(
subId,
+ isCarrierMerged(subId),
defaultNetworkName,
networkNameSeparator,
globalMobileDataSettingChangedEvent,
)
}
+ private fun updateRepos(newInfos: List<SubscriptionModel>) {
+ dropUnusedReposFromCache(newInfos)
+ subIdRepositoryCache.forEach { (subId, repo) ->
+ repo.setIsCarrierMerged(isCarrierMerged(subId))
+ }
+ }
+
+ private fun isCarrierMerged(subId: Int): Boolean {
+ return subId == carrierMergedSubId.value
+ }
+
private fun dropUnusedReposFromCache(newInfos: List<SubscriptionModel>) {
// Remove any connection repository from the cache that isn't in the new set of IDs. They
// will get garbage collected once their subscribers go away
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt
index 9427c6b..003df24 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt
@@ -22,8 +22,8 @@
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState.Connected
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
+import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -138,7 +138,11 @@
defaultMobileIconMapping,
defaultMobileIconGroup,
) { info, mapping, defaultGroup ->
- mapping[info.resolvedNetworkType.lookupKey] ?: defaultGroup
+ when (info.resolvedNetworkType) {
+ is ResolvedNetworkType.CarrierMergedNetworkType ->
+ info.resolvedNetworkType.iconGroupOverride
+ else -> mapping[info.resolvedNetworkType.lookupKey] ?: defaultGroup
+ }
}
.stateIn(scope, SharingStarted.WhileSubscribed(), defaultMobileIconGroup.value)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/model/WifiNetworkModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/model/WifiNetworkModel.kt
index 4251d18..da2daf2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/model/WifiNetworkModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/model/WifiNetworkModel.kt
@@ -16,13 +16,18 @@
package com.android.systemui.statusbar.pipeline.wifi.data.model
+import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID
import androidx.annotation.VisibleForTesting
import com.android.systemui.log.table.TableRowLogger
import com.android.systemui.log.table.Diffable
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS
/** Provides information about the current wifi network. */
sealed class WifiNetworkModel : Diffable<WifiNetworkModel> {
+ // TODO(b/238425913): Have a better, more unified strategy for diff-logging instead of
+ // copy-pasting the column names for each sub-object.
+
/**
* A model representing that we couldn't fetch any wifi information.
*
@@ -41,8 +46,43 @@
override fun logFull(row: TableRowLogger) {
row.logChange(COL_NETWORK_TYPE, TYPE_UNAVAILABLE)
row.logChange(COL_NETWORK_ID, NETWORK_ID_DEFAULT)
+ row.logChange(COL_SUB_ID, SUB_ID_DEFAULT)
row.logChange(COL_VALIDATED, false)
row.logChange(COL_LEVEL, LEVEL_DEFAULT)
+ row.logChange(COL_NUM_LEVELS, NUM_LEVELS_DEFAULT)
+ row.logChange(COL_SSID, null)
+ row.logChange(COL_PASSPOINT_ACCESS_POINT, false)
+ row.logChange(COL_ONLINE_SIGN_UP, false)
+ row.logChange(COL_PASSPOINT_NAME, null)
+ }
+ }
+
+ /**
+ * A model representing that the wifi information we received was invalid in some way.
+ */
+ data class Invalid(
+ /** A description of why the wifi information was invalid. */
+ val invalidReason: String,
+ ) : WifiNetworkModel() {
+ override fun toString() = "WifiNetwork.Invalid[$invalidReason]"
+ override fun logDiffs(prevVal: WifiNetworkModel, row: TableRowLogger) {
+ if (prevVal !is Invalid) {
+ logFull(row)
+ return
+ }
+
+ if (invalidReason != prevVal.invalidReason) {
+ row.logChange(COL_NETWORK_TYPE, "$TYPE_UNAVAILABLE $invalidReason")
+ }
+ }
+
+ override fun logFull(row: TableRowLogger) {
+ row.logChange(COL_NETWORK_TYPE, "$TYPE_UNAVAILABLE $invalidReason")
+ row.logChange(COL_NETWORK_ID, NETWORK_ID_DEFAULT)
+ row.logChange(COL_SUB_ID, SUB_ID_DEFAULT)
+ row.logChange(COL_VALIDATED, false)
+ row.logChange(COL_LEVEL, LEVEL_DEFAULT)
+ row.logChange(COL_NUM_LEVELS, NUM_LEVELS_DEFAULT)
row.logChange(COL_SSID, null)
row.logChange(COL_PASSPOINT_ACCESS_POINT, false)
row.logChange(COL_ONLINE_SIGN_UP, false)
@@ -59,18 +99,21 @@
return
}
- if (prevVal is CarrierMerged) {
- // The only difference between CarrierMerged and Inactive is the type
- row.logChange(COL_NETWORK_TYPE, TYPE_INACTIVE)
- return
- }
-
- // When changing from Active to Inactive, we need to log diffs to all the fields.
- logFullNonActiveNetwork(TYPE_INACTIVE, row)
+ // When changing to Inactive, we need to log diffs to all the fields.
+ logFull(row)
}
override fun logFull(row: TableRowLogger) {
- logFullNonActiveNetwork(TYPE_INACTIVE, row)
+ row.logChange(COL_NETWORK_TYPE, TYPE_INACTIVE)
+ row.logChange(COL_NETWORK_ID, NETWORK_ID_DEFAULT)
+ row.logChange(COL_SUB_ID, SUB_ID_DEFAULT)
+ row.logChange(COL_VALIDATED, false)
+ row.logChange(COL_LEVEL, LEVEL_DEFAULT)
+ row.logChange(COL_NUM_LEVELS, NUM_LEVELS_DEFAULT)
+ row.logChange(COL_SSID, null)
+ row.logChange(COL_PASSPOINT_ACCESS_POINT, false)
+ row.logChange(COL_ONLINE_SIGN_UP, false)
+ row.logChange(COL_PASSPOINT_NAME, null)
}
}
@@ -80,22 +123,75 @@
*
* See [android.net.wifi.WifiInfo.isCarrierMerged] for more information.
*/
- object CarrierMerged : WifiNetworkModel() {
- override fun toString() = "WifiNetwork.CarrierMerged"
+ data class CarrierMerged(
+ /**
+ * The [android.net.Network.netId] we received from
+ * [android.net.ConnectivityManager.NetworkCallback] in association with this wifi network.
+ *
+ * Importantly, **not** [android.net.wifi.WifiInfo.getNetworkId].
+ */
+ val networkId: Int,
+
+ /**
+ * The subscription ID that this connection represents.
+ *
+ * Comes from [android.net.wifi.WifiInfo.getSubscriptionId].
+ *
+ * Per that method, this value must not be [INVALID_SUBSCRIPTION_ID] (if it was invalid,
+ * then this is *not* a carrier merged network).
+ */
+ val subscriptionId: Int,
+
+ /**
+ * The signal level, guaranteed to be 0 <= level <= numberOfLevels.
+ */
+ val level: Int,
+
+ /**
+ * The maximum possible level.
+ */
+ val numberOfLevels: Int = DEFAULT_NUM_LEVELS,
+ ) : WifiNetworkModel() {
+ init {
+ require(level in MIN_VALID_LEVEL..numberOfLevels) {
+ "0 <= wifi level <= $numberOfLevels required; level was $level"
+ }
+ require(subscriptionId != INVALID_SUBSCRIPTION_ID) {
+ "subscription ID cannot be invalid"
+ }
+ }
override fun logDiffs(prevVal: WifiNetworkModel, row: TableRowLogger) {
- if (prevVal is CarrierMerged) {
+ if (prevVal !is CarrierMerged) {
+ logFull(row)
return
}
- if (prevVal is Inactive) {
- // The only difference between CarrierMerged and Inactive is the type.
- row.logChange(COL_NETWORK_TYPE, TYPE_CARRIER_MERGED)
- return
+ if (prevVal.networkId != networkId) {
+ row.logChange(COL_NETWORK_ID, networkId)
}
+ if (prevVal.subscriptionId != subscriptionId) {
+ row.logChange(COL_SUB_ID, subscriptionId)
+ }
+ if (prevVal.level != level) {
+ row.logChange(COL_LEVEL, level)
+ }
+ if (prevVal.numberOfLevels != numberOfLevels) {
+ row.logChange(COL_NUM_LEVELS, numberOfLevels)
+ }
+ }
- // When changing from Active to CarrierMerged, we need to log diffs to all the fields.
- logFullNonActiveNetwork(TYPE_CARRIER_MERGED, row)
+ override fun logFull(row: TableRowLogger) {
+ row.logChange(COL_NETWORK_TYPE, TYPE_CARRIER_MERGED)
+ row.logChange(COL_NETWORK_ID, networkId)
+ row.logChange(COL_SUB_ID, subscriptionId)
+ row.logChange(COL_VALIDATED, true)
+ row.logChange(COL_LEVEL, level)
+ row.logChange(COL_NUM_LEVELS, numberOfLevels)
+ row.logChange(COL_SSID, null)
+ row.logChange(COL_PASSPOINT_ACCESS_POINT, false)
+ row.logChange(COL_ONLINE_SIGN_UP, false)
+ row.logChange(COL_PASSPOINT_NAME, null)
}
}
@@ -137,38 +233,50 @@
override fun logDiffs(prevVal: WifiNetworkModel, row: TableRowLogger) {
if (prevVal !is Active) {
- row.logChange(COL_NETWORK_TYPE, TYPE_ACTIVE)
+ logFull(row)
+ return
}
- if (prevVal !is Active || prevVal.networkId != networkId) {
+ if (prevVal.networkId != networkId) {
row.logChange(COL_NETWORK_ID, networkId)
}
- if (prevVal !is Active || prevVal.isValidated != isValidated) {
+ if (prevVal.isValidated != isValidated) {
row.logChange(COL_VALIDATED, isValidated)
}
- if (prevVal !is Active || prevVal.level != level) {
+ if (prevVal.level != level) {
row.logChange(COL_LEVEL, level)
}
- if (prevVal !is Active || prevVal.ssid != ssid) {
+ if (prevVal.ssid != ssid) {
row.logChange(COL_SSID, ssid)
}
// TODO(b/238425913): The passpoint-related values are frequently never used, so it
// would be great to not log them when they're not used.
- if (prevVal !is Active || prevVal.isPasspointAccessPoint != isPasspointAccessPoint) {
+ if (prevVal.isPasspointAccessPoint != isPasspointAccessPoint) {
row.logChange(COL_PASSPOINT_ACCESS_POINT, isPasspointAccessPoint)
}
- if (prevVal !is Active ||
- prevVal.isOnlineSignUpForPasspointAccessPoint !=
+ if (prevVal.isOnlineSignUpForPasspointAccessPoint !=
isOnlineSignUpForPasspointAccessPoint) {
row.logChange(COL_ONLINE_SIGN_UP, isOnlineSignUpForPasspointAccessPoint)
}
- if (prevVal !is Active ||
- prevVal.passpointProviderFriendlyName != passpointProviderFriendlyName) {
+ if (prevVal.passpointProviderFriendlyName != passpointProviderFriendlyName) {
row.logChange(COL_PASSPOINT_NAME, passpointProviderFriendlyName)
}
}
+ override fun logFull(row: TableRowLogger) {
+ row.logChange(COL_NETWORK_TYPE, TYPE_ACTIVE)
+ row.logChange(COL_NETWORK_ID, networkId)
+ row.logChange(COL_SUB_ID, null)
+ row.logChange(COL_VALIDATED, isValidated)
+ row.logChange(COL_LEVEL, level)
+ row.logChange(COL_NUM_LEVELS, null)
+ row.logChange(COL_SSID, ssid)
+ row.logChange(COL_PASSPOINT_ACCESS_POINT, isPasspointAccessPoint)
+ row.logChange(COL_ONLINE_SIGN_UP, isOnlineSignUpForPasspointAccessPoint)
+ row.logChange(COL_PASSPOINT_NAME, passpointProviderFriendlyName)
+ }
+
override fun toString(): String {
// Only include the passpoint-related values in the string if we have them. (Most
// networks won't have them so they'll be mostly clutter.)
@@ -189,21 +297,13 @@
companion object {
@VisibleForTesting
- internal const val MIN_VALID_LEVEL = 0
- @VisibleForTesting
internal const val MAX_VALID_LEVEL = 4
}
}
- internal fun logFullNonActiveNetwork(type: String, row: TableRowLogger) {
- row.logChange(COL_NETWORK_TYPE, type)
- row.logChange(COL_NETWORK_ID, NETWORK_ID_DEFAULT)
- row.logChange(COL_VALIDATED, false)
- row.logChange(COL_LEVEL, LEVEL_DEFAULT)
- row.logChange(COL_SSID, null)
- row.logChange(COL_PASSPOINT_ACCESS_POINT, false)
- row.logChange(COL_ONLINE_SIGN_UP, false)
- row.logChange(COL_PASSPOINT_NAME, null)
+ companion object {
+ @VisibleForTesting
+ internal const val MIN_VALID_LEVEL = 0
}
}
@@ -214,12 +314,16 @@
const val COL_NETWORK_TYPE = "type"
const val COL_NETWORK_ID = "networkId"
+const val COL_SUB_ID = "subscriptionId"
const val COL_VALIDATED = "isValidated"
const val COL_LEVEL = "level"
+const val COL_NUM_LEVELS = "maxLevel"
const val COL_SSID = "ssid"
const val COL_PASSPOINT_ACCESS_POINT = "isPasspointAccessPoint"
const val COL_ONLINE_SIGN_UP = "isOnlineSignUpForPasspointAccessPoint"
const val COL_PASSPOINT_NAME = "passpointProviderFriendlyName"
val LEVEL_DEFAULT: String? = null
+val NUM_LEVELS_DEFAULT: String? = null
val NETWORK_ID_DEFAULT: String? = null
+val SUB_ID_DEFAULT: String? = null
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoModeWifiDataSource.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoModeWifiDataSource.kt
index c588945..caac8fa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoModeWifiDataSource.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoModeWifiDataSource.kt
@@ -22,6 +22,7 @@
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.demomode.DemoMode.COMMAND_NETWORK
import com.android.systemui.demomode.DemoModeController
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS
import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.FakeWifiEventModel
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
@@ -43,10 +44,10 @@
private fun Bundle.toWifiEvent(): FakeWifiEventModel? {
val wifi = getString("wifi") ?: return null
- return if (wifi == "show") {
- activeWifiEvent()
- } else {
- FakeWifiEventModel.WifiDisabled
+ return when (wifi) {
+ "show" -> activeWifiEvent()
+ "carriermerged" -> carrierMergedWifiEvent()
+ else -> FakeWifiEventModel.WifiDisabled
}
}
@@ -64,6 +65,14 @@
)
}
+ private fun Bundle.carrierMergedWifiEvent(): FakeWifiEventModel.CarrierMerged {
+ val subId = getString("slot")?.toInt() ?: DEFAULT_CARRIER_MERGED_SUB_ID
+ val level = getString("level")?.toInt() ?: 0
+ val numberOfLevels = getString("numlevels")?.toInt() ?: DEFAULT_NUM_LEVELS
+
+ return FakeWifiEventModel.CarrierMerged(subId, level, numberOfLevels)
+ }
+
private fun String.toActivity(): Int =
when (this) {
"inout" -> WifiManager.TrafficStateCallback.DATA_ACTIVITY_INOUT
@@ -71,4 +80,8 @@
"out" -> WifiManager.TrafficStateCallback.DATA_ACTIVITY_OUT
else -> WifiManager.TrafficStateCallback.DATA_ACTIVITY_NONE
}
+
+ companion object {
+ const val DEFAULT_CARRIER_MERGED_SUB_ID = 10
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoWifiRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoWifiRepository.kt
index be3d7d4..e161b3e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoWifiRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoWifiRepository.kt
@@ -66,6 +66,7 @@
private fun processEvent(event: FakeWifiEventModel) =
when (event) {
is FakeWifiEventModel.Wifi -> processEnabledWifiState(event)
+ is FakeWifiEventModel.CarrierMerged -> processCarrierMergedWifiState(event)
is FakeWifiEventModel.WifiDisabled -> processDisabledWifiState()
}
@@ -85,6 +86,14 @@
_wifiNetwork.value = event.toWifiNetworkModel()
}
+ private fun processCarrierMergedWifiState(event: FakeWifiEventModel.CarrierMerged) {
+ _isWifiEnabled.value = true
+ _isWifiDefault.value = true
+ // TODO(b/238425913): Support activity in demo mode.
+ _wifiActivity.value = DataActivityModel(hasActivityIn = false, hasActivityOut = false)
+ _wifiNetwork.value = event.toCarrierMergedModel()
+ }
+
private fun FakeWifiEventModel.Wifi.toWifiNetworkModel(): WifiNetworkModel =
WifiNetworkModel.Active(
networkId = DEMO_NET_ID,
@@ -99,6 +108,14 @@
passpointProviderFriendlyName = null,
)
+ private fun FakeWifiEventModel.CarrierMerged.toCarrierMergedModel(): WifiNetworkModel =
+ WifiNetworkModel.CarrierMerged(
+ networkId = DEMO_NET_ID,
+ subscriptionId = subscriptionId,
+ level = level,
+ numberOfLevels = numberOfLevels,
+ )
+
companion object {
private const val DEMO_NET_ID = 1234
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/model/FakeWifiEventModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/model/FakeWifiEventModel.kt
index 2353fb8..518f8ce 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/model/FakeWifiEventModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/model/FakeWifiEventModel.kt
@@ -29,5 +29,11 @@
val validated: Boolean?,
) : FakeWifiEventModel
+ data class CarrierMerged(
+ val subscriptionId: Int,
+ val level: Int,
+ val numberOfLevels: Int,
+ ) : FakeWifiEventModel
+
object WifiDisabled : FakeWifiEventModel
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
index c47c20d..d26499c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
@@ -29,6 +29,7 @@
import android.net.wifi.WifiInfo
import android.net.wifi.WifiManager
import android.net.wifi.WifiManager.TrafficStateCallback
+import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID
import com.android.settingslib.Utils
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
@@ -269,7 +270,19 @@
wifiManager: WifiManager,
): WifiNetworkModel {
return if (wifiInfo.isCarrierMerged) {
- WifiNetworkModel.CarrierMerged
+ if (wifiInfo.subscriptionId == INVALID_SUBSCRIPTION_ID) {
+ WifiNetworkModel.Invalid(CARRIER_MERGED_INVALID_SUB_ID_REASON)
+ } else {
+ WifiNetworkModel.CarrierMerged(
+ networkId = network.getNetId(),
+ subscriptionId = wifiInfo.subscriptionId,
+ level = wifiManager.calculateSignalLevel(wifiInfo.rssi),
+ // The WiFi signal level returned by WifiManager#calculateSignalLevel start
+ // from 0, so WifiManager#getMaxSignalLevel + 1 represents the total level
+ // buckets count.
+ numberOfLevels = wifiManager.maxSignalLevel + 1,
+ )
+ }
} else {
WifiNetworkModel.Active(
network.getNetId(),
@@ -302,6 +315,9 @@
.build()
private const val WIFI_NETWORK_CALLBACK_NAME = "wifiNetworkModel"
+
+ private const val CARRIER_MERGED_INVALID_SUB_ID_REASON =
+ "Wifi network was carrier merged but had invalid sub ID"
}
@SysUISingleton
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractor.kt
index 980560a..86dcd18 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractor.kt
@@ -66,6 +66,7 @@
override val ssid: Flow<String?> = wifiRepository.wifiNetwork.map { info ->
when (info) {
is WifiNetworkModel.Unavailable -> null
+ is WifiNetworkModel.Invalid -> null
is WifiNetworkModel.Inactive -> null
is WifiNetworkModel.CarrierMerged -> null
is WifiNetworkModel.Active -> when {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt
index 824b597..95431af 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt
@@ -83,6 +83,7 @@
private fun WifiNetworkModel.icon(): WifiIcon {
return when (this) {
is WifiNetworkModel.Unavailable -> WifiIcon.Hidden
+ is WifiNetworkModel.Invalid -> WifiIcon.Hidden
is WifiNetworkModel.CarrierMerged -> WifiIcon.Hidden
is WifiNetworkModel.Inactive -> WifiIcon.Visible(
res = WIFI_NO_NETWORK,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index c9ed0cb..f8c17e8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -109,6 +109,8 @@
private static final long FOCUS_ANIMATION_FADE_IN_DELAY = 33;
private static final long FOCUS_ANIMATION_FADE_IN_DURATION = 83;
private static final float FOCUS_ANIMATION_MIN_SCALE = 0.5f;
+ private static final long DEFOCUS_ANIMATION_FADE_OUT_DELAY = 120;
+ private static final long DEFOCUS_ANIMATION_CROSSFADE_DELAY = 180;
public final Object mToken = new Object();
@@ -421,7 +423,7 @@
}
@VisibleForTesting
- void onDefocus(boolean animate, boolean logClose) {
+ void onDefocus(boolean animate, boolean logClose, @Nullable Runnable doAfterDefocus) {
mController.removeRemoteInput(mEntry, mToken);
mEntry.remoteInputText = mEditText.getText();
@@ -431,18 +433,20 @@
ViewGroup parent = (ViewGroup) getParent();
if (animate && parent != null && mIsFocusAnimationFlagActive) {
-
ViewGroup grandParent = (ViewGroup) parent.getParent();
ViewGroupOverlay overlay = parent.getOverlay();
+ View actionsContainer = getActionsContainerLayout();
+ int actionsContainerHeight =
+ actionsContainer != null ? actionsContainer.getHeight() : 0;
// After adding this RemoteInputView to the overlay of the parent (and thus removing
// it from the parent itself), the parent will shrink in height. This causes the
// overlay to be moved. To correct the position of the overlay we need to offset it.
- int overlayOffsetY = getMaxSiblingHeight() - getHeight();
+ int overlayOffsetY = actionsContainerHeight - getHeight();
overlay.add(this);
if (grandParent != null) grandParent.setClipChildren(false);
- Animator animator = getDefocusAnimator(overlayOffsetY);
+ Animator animator = getDefocusAnimator(actionsContainer, overlayOffsetY);
View self = this;
animator.addListener(new AnimatorListenerAdapter() {
@Override
@@ -454,8 +458,12 @@
if (mWrapper != null) {
mWrapper.setRemoteInputVisible(false);
}
+ if (doAfterDefocus != null) {
+ doAfterDefocus.run();
+ }
}
});
+ if (actionsContainer != null) actionsContainer.setAlpha(0f);
animator.start();
} else if (animate && mRevealParams != null && mRevealParams.radius > 0) {
@@ -474,6 +482,7 @@
reveal.start();
} else {
setVisibility(GONE);
+ if (doAfterDefocus != null) doAfterDefocus.run();
if (mWrapper != null) {
mWrapper.setRemoteInputVisible(false);
}
@@ -596,10 +605,8 @@
/**
* Focuses the RemoteInputView and animates its appearance
- *
- * @param crossFadeView view that will be crossfaded during the appearance animation
*/
- public void focusAnimated(View crossFadeView) {
+ public void focusAnimated() {
if (!mIsFocusAnimationFlagActive && getVisibility() != VISIBLE
&& mRevealParams != null) {
android.animation.Animator animator = mRevealParams.createCircularRevealAnimator(this);
@@ -609,7 +616,7 @@
} else if (mIsFocusAnimationFlagActive && getVisibility() != VISIBLE) {
mIsAnimatingAppearance = true;
setAlpha(0f);
- Animator focusAnimator = getFocusAnimator(crossFadeView);
+ Animator focusAnimator = getFocusAnimator(getActionsContainerLayout());
focusAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation, boolean isReverse) {
@@ -661,6 +668,23 @@
}
private void reset() {
+ if (mIsFocusAnimationFlagActive) {
+ mProgressBar.setVisibility(INVISIBLE);
+ mResetting = true;
+ mSending = false;
+ onDefocus(true /* animate */, false /* logClose */, () -> {
+ mEntry.remoteInputTextWhenReset = SpannedString.valueOf(mEditText.getText());
+ mEditText.getText().clear();
+ mEditText.setEnabled(isAggregatedVisible());
+ mSendButton.setVisibility(VISIBLE);
+ mController.removeSpinning(mEntry.getKey(), mToken);
+ updateSendButton();
+ setAttachment(null);
+ mResetting = false;
+ });
+ return;
+ }
+
mResetting = true;
mSending = false;
mEntry.remoteInputTextWhenReset = SpannedString.valueOf(mEditText.getText());
@@ -671,7 +695,7 @@
mProgressBar.setVisibility(INVISIBLE);
mController.removeSpinning(mEntry.getKey(), mToken);
updateSendButton();
- onDefocus(false /* animate */, false /* logClose */);
+ onDefocus(false /* animate */, false /* logClose */, null /* doAfterDefocus */);
setAttachment(null);
mResetting = false;
@@ -825,23 +849,22 @@
}
/**
- * @return max sibling height (0 in case of no siblings)
+ * @return action button container view (i.e. ViewGroup containing Reply button etc.)
*/
- public int getMaxSiblingHeight() {
+ public View getActionsContainerLayout() {
ViewGroup parentView = (ViewGroup) getParent();
- int maxHeight = 0;
- if (parentView == null) return 0;
- for (int i = 0; i < parentView.getChildCount(); i++) {
- View siblingView = parentView.getChildAt(i);
- if (siblingView != this) maxHeight = Math.max(maxHeight, siblingView.getHeight());
- }
- return maxHeight;
+ if (parentView == null) return null;
+ return parentView.findViewById(com.android.internal.R.id.actions_container_layout);
}
/**
* Creates an animator for the focus animation.
+ *
+ * @param fadeOutView View that will be faded out during the focus animation.
*/
- private Animator getFocusAnimator(View crossFadeView) {
+ private Animator getFocusAnimator(@Nullable View fadeOutView) {
+ final AnimatorSet animatorSet = new AnimatorSet();
+
final Animator alphaAnimator = ObjectAnimator.ofFloat(this, View.ALPHA, 0f, 1f);
alphaAnimator.setStartDelay(FOCUS_ANIMATION_FADE_IN_DELAY);
alphaAnimator.setDuration(FOCUS_ANIMATION_FADE_IN_DURATION);
@@ -854,30 +877,36 @@
scaleAnimator.setDuration(FOCUS_ANIMATION_TOTAL_DURATION);
scaleAnimator.setInterpolator(InterpolatorsAndroidX.FAST_OUT_SLOW_IN);
- final Animator crossFadeViewAlphaAnimator =
- ObjectAnimator.ofFloat(crossFadeView, View.ALPHA, 1f, 0f);
- crossFadeViewAlphaAnimator.setDuration(FOCUS_ANIMATION_CROSSFADE_DURATION);
- crossFadeViewAlphaAnimator.setInterpolator(InterpolatorsAndroidX.LINEAR);
- alphaAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation, boolean isReverse) {
- crossFadeView.setAlpha(1f);
- }
- });
-
- final AnimatorSet animatorSet = new AnimatorSet();
- animatorSet.playTogether(alphaAnimator, scaleAnimator, crossFadeViewAlphaAnimator);
+ if (fadeOutView == null) {
+ animatorSet.playTogether(alphaAnimator, scaleAnimator);
+ } else {
+ final Animator fadeOutViewAlphaAnimator =
+ ObjectAnimator.ofFloat(fadeOutView, View.ALPHA, 1f, 0f);
+ fadeOutViewAlphaAnimator.setDuration(FOCUS_ANIMATION_CROSSFADE_DURATION);
+ fadeOutViewAlphaAnimator.setInterpolator(InterpolatorsAndroidX.LINEAR);
+ animatorSet.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation, boolean isReverse) {
+ fadeOutView.setAlpha(1f);
+ }
+ });
+ animatorSet.playTogether(alphaAnimator, scaleAnimator, fadeOutViewAlphaAnimator);
+ }
return animatorSet;
}
/**
* Creates an animator for the defocus animation.
*
- * @param offsetY The RemoteInputView will be offset by offsetY during the animation
+ * @param fadeInView View that will be faded in during the defocus animation.
+ * @param offsetY The RemoteInputView will be offset by offsetY during the animation
*/
- private Animator getDefocusAnimator(int offsetY) {
+ private Animator getDefocusAnimator(@Nullable View fadeInView, int offsetY) {
+ final AnimatorSet animatorSet = new AnimatorSet();
+
final Animator alphaAnimator = ObjectAnimator.ofFloat(this, View.ALPHA, 1f, 0f);
- alphaAnimator.setDuration(FOCUS_ANIMATION_CROSSFADE_DURATION);
+ alphaAnimator.setDuration(FOCUS_ANIMATION_FADE_IN_DURATION);
+ alphaAnimator.setStartDelay(DEFOCUS_ANIMATION_FADE_OUT_DELAY);
alphaAnimator.setInterpolator(InterpolatorsAndroidX.LINEAR);
ValueAnimator scaleAnimator = ValueAnimator.ofFloat(1f, FOCUS_ANIMATION_MIN_SCALE);
@@ -893,8 +922,17 @@
}
});
- final AnimatorSet animatorSet = new AnimatorSet();
- animatorSet.playTogether(alphaAnimator, scaleAnimator);
+ if (fadeInView == null) {
+ animatorSet.playTogether(alphaAnimator, scaleAnimator);
+ } else {
+ fadeInView.forceHasOverlappingRendering(false);
+ Animator fadeInViewAlphaAnimator =
+ ObjectAnimator.ofFloat(fadeInView, View.ALPHA, 0f, 1f);
+ fadeInViewAlphaAnimator.setDuration(FOCUS_ANIMATION_FADE_IN_DURATION);
+ fadeInViewAlphaAnimator.setInterpolator(InterpolatorsAndroidX.LINEAR);
+ fadeInViewAlphaAnimator.setStartDelay(DEFOCUS_ANIMATION_CROSSFADE_DELAY);
+ animatorSet.playTogether(alphaAnimator, scaleAnimator, fadeInViewAlphaAnimator);
+ }
return animatorSet;
}
@@ -1011,7 +1049,8 @@
if (isFocusable() && isEnabled()) {
setInnerFocusable(false);
if (mRemoteInputView != null) {
- mRemoteInputView.onDefocus(animate, true /* logClose */);
+ mRemoteInputView
+ .onDefocus(animate, true /* logClose */, null /* doAfterDefocus */);
}
mShowImeOnInputConnection = false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/stylus/StylusFirstUsageListener.kt b/packages/SystemUI/src/com/android/systemui/stylus/StylusFirstUsageListener.kt
deleted file mode 100644
index 154c6e2..0000000
--- a/packages/SystemUI/src/com/android/systemui/stylus/StylusFirstUsageListener.kt
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.systemui.stylus
-
-import android.content.Context
-import android.hardware.BatteryState
-import android.hardware.input.InputManager
-import android.os.Handler
-import android.util.Log
-import android.view.InputDevice
-import androidx.annotation.VisibleForTesting
-import com.android.systemui.CoreStartable
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Background
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
-import java.util.concurrent.Executor
-import javax.inject.Inject
-
-/**
- * A listener that detects when a stylus has first been used, by detecting 1) the presence of an
- * internal SOURCE_STYLUS with a battery, or 2) any added SOURCE_STYLUS device with a bluetooth
- * address.
- */
-@SysUISingleton
-class StylusFirstUsageListener
-@Inject
-constructor(
- private val context: Context,
- private val inputManager: InputManager,
- private val stylusManager: StylusManager,
- private val featureFlags: FeatureFlags,
- @Background private val executor: Executor,
- @Background private val handler: Handler,
-) : CoreStartable, StylusManager.StylusCallback, InputManager.InputDeviceBatteryListener {
-
- // Set must be only accessed from the background handler, which is the same handler that
- // runs the StylusManager callbacks.
- private val internalStylusDeviceIds: MutableSet<Int> = mutableSetOf()
- @VisibleForTesting var hasStarted = false
-
- override fun start() {
- if (true) return // TODO(b/261826950): remove on main
- if (hasStarted) return
- if (!featureFlags.isEnabled(Flags.TRACK_STYLUS_EVER_USED)) return
- if (inputManager.isStylusEverUsed(context)) return
- if (!hostDeviceSupportsStylusInput()) return
-
- hasStarted = true
- inputManager.inputDeviceIds.forEach(this::onStylusAdded)
- stylusManager.registerCallback(this)
- stylusManager.startListener()
- }
-
- override fun onStylusAdded(deviceId: Int) {
- if (!hasStarted) return
-
- val device = inputManager.getInputDevice(deviceId) ?: return
- if (device.isExternal || !device.supportsSource(InputDevice.SOURCE_STYLUS)) return
-
- try {
- inputManager.addInputDeviceBatteryListener(deviceId, executor, this)
- internalStylusDeviceIds += deviceId
- } catch (e: SecurityException) {
- Log.e(TAG, "$e: Failed to register battery listener for $deviceId ${device.name}.")
- }
- }
-
- override fun onStylusRemoved(deviceId: Int) {
- if (!hasStarted) return
-
- if (!internalStylusDeviceIds.contains(deviceId)) return
- try {
- inputManager.removeInputDeviceBatteryListener(deviceId, this)
- internalStylusDeviceIds.remove(deviceId)
- } catch (e: SecurityException) {
- Log.e(TAG, "$e: Failed to remove registered battery listener for $deviceId.")
- }
- }
-
- override fun onStylusBluetoothConnected(deviceId: Int, btAddress: String) {
- if (!hasStarted) return
-
- onRemoteDeviceFound()
- }
-
- override fun onBatteryStateChanged(
- deviceId: Int,
- eventTimeMillis: Long,
- batteryState: BatteryState
- ) {
- if (!hasStarted) return
-
- if (batteryState.isPresent) {
- onRemoteDeviceFound()
- }
- }
-
- private fun onRemoteDeviceFound() {
- inputManager.setStylusEverUsed(context, true)
- cleanupListeners()
- }
-
- private fun cleanupListeners() {
- stylusManager.unregisterCallback(this)
- handler.post {
- internalStylusDeviceIds.forEach {
- inputManager.removeInputDeviceBatteryListener(it, this)
- }
- }
- }
-
- private fun hostDeviceSupportsStylusInput(): Boolean {
- return inputManager.inputDeviceIds
- .asSequence()
- .mapNotNull { inputManager.getInputDevice(it) }
- .any { it.supportsSource(InputDevice.SOURCE_STYLUS) && !it.isExternal }
- }
-
- companion object {
- private val TAG = StylusFirstUsageListener::class.simpleName.orEmpty()
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/stylus/StylusManager.kt b/packages/SystemUI/src/com/android/systemui/stylus/StylusManager.kt
index 302d6a9..b22af3b 100644
--- a/packages/SystemUI/src/com/android/systemui/stylus/StylusManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/stylus/StylusManager.kt
@@ -18,6 +18,8 @@
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
+import android.content.Context
+import android.hardware.BatteryState
import android.hardware.input.InputManager
import android.os.Handler
import android.util.ArrayMap
@@ -25,6 +27,8 @@
import android.view.InputDevice
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
import java.util.concurrent.CopyOnWriteArrayList
import java.util.concurrent.Executor
import javax.inject.Inject
@@ -37,25 +41,37 @@
class StylusManager
@Inject
constructor(
+ private val context: Context,
private val inputManager: InputManager,
private val bluetoothAdapter: BluetoothAdapter?,
@Background private val handler: Handler,
@Background private val executor: Executor,
-) : InputManager.InputDeviceListener, BluetoothAdapter.OnMetadataChangedListener {
+ private val featureFlags: FeatureFlags,
+) :
+ InputManager.InputDeviceListener,
+ InputManager.InputDeviceBatteryListener,
+ BluetoothAdapter.OnMetadataChangedListener {
private val stylusCallbacks: CopyOnWriteArrayList<StylusCallback> = CopyOnWriteArrayList()
private val stylusBatteryCallbacks: CopyOnWriteArrayList<StylusBatteryCallback> =
CopyOnWriteArrayList()
// This map should only be accessed on the handler
private val inputDeviceAddressMap: MutableMap<Int, String?> = ArrayMap()
+ // This variable should only be accessed on the handler
+ private var hasStarted: Boolean = false
/**
* Starts listening to InputManager InputDevice events. Will also load the InputManager snapshot
* at time of starting.
*/
fun startListener() {
- addExistingStylusToMap()
- inputManager.registerInputDeviceListener(this, handler)
+ handler.post {
+ if (hasStarted) return@post
+ hasStarted = true
+ addExistingStylusToMap()
+
+ inputManager.registerInputDeviceListener(this, handler)
+ }
}
/** Registers a StylusCallback to listen to stylus events. */
@@ -77,26 +93,33 @@
}
override fun onInputDeviceAdded(deviceId: Int) {
+ if (!hasStarted) return
+
val device: InputDevice = inputManager.getInputDevice(deviceId) ?: return
if (!device.supportsSource(InputDevice.SOURCE_STYLUS)) return
- // TODO(b/257936830): get address once input api available
- val btAddress: String? = null
+ if (!device.isExternal) {
+ registerBatteryListener(deviceId)
+ }
+
+ val btAddress: String? = device.bluetoothAddress
inputDeviceAddressMap[deviceId] = btAddress
executeStylusCallbacks { cb -> cb.onStylusAdded(deviceId) }
if (btAddress != null) {
+ onStylusUsed()
onStylusBluetoothConnected(btAddress)
executeStylusCallbacks { cb -> cb.onStylusBluetoothConnected(deviceId, btAddress) }
}
}
override fun onInputDeviceChanged(deviceId: Int) {
+ if (!hasStarted) return
+
val device: InputDevice = inputManager.getInputDevice(deviceId) ?: return
if (!device.supportsSource(InputDevice.SOURCE_STYLUS)) return
- // TODO(b/257936830): get address once input api available
- val currAddress: String? = null
+ val currAddress: String? = device.bluetoothAddress
val prevAddress: String? = inputDeviceAddressMap[deviceId]
inputDeviceAddressMap[deviceId] = currAddress
@@ -112,7 +135,10 @@
}
override fun onInputDeviceRemoved(deviceId: Int) {
+ if (!hasStarted) return
+
if (!inputDeviceAddressMap.contains(deviceId)) return
+ unregisterBatteryListener(deviceId)
val btAddress: String? = inputDeviceAddressMap[deviceId]
inputDeviceAddressMap.remove(deviceId)
@@ -124,13 +150,14 @@
}
override fun onMetadataChanged(device: BluetoothDevice, key: Int, value: ByteArray?) {
- handler.post executeMetadataChanged@{
- if (key != BluetoothDevice.METADATA_MAIN_CHARGING || value == null)
- return@executeMetadataChanged
+ handler.post {
+ if (!hasStarted) return@post
+
+ if (key != BluetoothDevice.METADATA_MAIN_CHARGING || value == null) return@post
val inputDeviceId: Int =
inputDeviceAddressMap.filterValues { it == device.address }.keys.firstOrNull()
- ?: return@executeMetadataChanged
+ ?: return@post
val isCharging = String(value) == "true"
@@ -140,6 +167,24 @@
}
}
+ override fun onBatteryStateChanged(
+ deviceId: Int,
+ eventTimeMillis: Long,
+ batteryState: BatteryState
+ ) {
+ handler.post {
+ if (!hasStarted) return@post
+
+ if (batteryState.isPresent) {
+ onStylusUsed()
+ }
+
+ executeStylusBatteryCallbacks { cb ->
+ cb.onStylusUsiBatteryStateChanged(deviceId, eventTimeMillis, batteryState)
+ }
+ }
+ }
+
private fun onStylusBluetoothConnected(btAddress: String) {
val device: BluetoothDevice = bluetoothAdapter?.getRemoteDevice(btAddress) ?: return
try {
@@ -158,6 +203,20 @@
}
}
+ /**
+ * An InputDevice that supports [InputDevice.SOURCE_STYLUS] may still be present even when a
+ * physical stylus device has never been used. This method is run when 1) a USI stylus battery
+ * event happens, or 2) a bluetooth stylus is connected, as they are both indicators that a
+ * physical stylus device has actually been used.
+ */
+ private fun onStylusUsed() {
+ if (!featureFlags.isEnabled(Flags.TRACK_STYLUS_EVER_USED)) return
+ if (inputManager.isStylusEverUsed(context)) return
+
+ inputManager.setStylusEverUsed(context, true)
+ executeStylusCallbacks { cb -> cb.onStylusFirstUsed() }
+ }
+
private fun executeStylusCallbacks(run: (cb: StylusCallback) -> Unit) {
stylusCallbacks.forEach(run)
}
@@ -166,31 +225,68 @@
stylusBatteryCallbacks.forEach(run)
}
+ private fun registerBatteryListener(deviceId: Int) {
+ try {
+ inputManager.addInputDeviceBatteryListener(deviceId, executor, this)
+ } catch (e: SecurityException) {
+ Log.e(TAG, "$e: Failed to register battery listener for $deviceId.")
+ }
+ }
+
+ private fun unregisterBatteryListener(deviceId: Int) {
+ // If deviceId wasn't registered, the result is a no-op, so an "is registered"
+ // check is not needed.
+ try {
+ inputManager.removeInputDeviceBatteryListener(deviceId, this)
+ } catch (e: SecurityException) {
+ Log.e(TAG, "$e: Failed to remove registered battery listener for $deviceId.")
+ }
+ }
+
private fun addExistingStylusToMap() {
for (deviceId: Int in inputManager.inputDeviceIds) {
val device: InputDevice = inputManager.getInputDevice(deviceId) ?: continue
if (device.supportsSource(InputDevice.SOURCE_STYLUS)) {
- // TODO(b/257936830): get address once input api available
- inputDeviceAddressMap[deviceId] = null
+ inputDeviceAddressMap[deviceId] = device.bluetoothAddress
+
+ if (!device.isExternal) { // TODO(b/263556967): add supportsUsi check once available
+ // For most devices, an active (non-bluetooth) stylus is represented by an
+ // internal InputDevice. This InputDevice will be present in InputManager
+ // before CoreStartables run, and will not be removed.
+ // In many cases, it reports the battery level of the stylus.
+ registerBatteryListener(deviceId)
+ }
}
}
}
- /** Callback interface to receive events from the StylusManager. */
+ /**
+ * Callback interface to receive events from the StylusManager. All callbacks are run on the
+ * same background handler.
+ */
interface StylusCallback {
fun onStylusAdded(deviceId: Int) {}
fun onStylusRemoved(deviceId: Int) {}
fun onStylusBluetoothConnected(deviceId: Int, btAddress: String) {}
fun onStylusBluetoothDisconnected(deviceId: Int, btAddress: String) {}
+ fun onStylusFirstUsed() {}
}
- /** Callback interface to receive stylus battery events from the StylusManager. */
+ /**
+ * Callback interface to receive stylus battery events from the StylusManager. All callbacks are
+ * runs on the same background handler.
+ */
interface StylusBatteryCallback {
fun onStylusBluetoothChargingStateChanged(
inputDeviceId: Int,
btDevice: BluetoothDevice,
isCharging: Boolean
) {}
+ fun onStylusUsiBatteryStateChanged(
+ deviceId: Int,
+ eventTimeMillis: Long,
+ batteryState: BatteryState,
+ ) {}
}
companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerStartable.kt b/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerStartable.kt
index 11233dd..5a8850a 100644
--- a/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerStartable.kt
@@ -18,14 +18,11 @@
import android.hardware.BatteryState
import android.hardware.input.InputManager
-import android.util.Log
import android.view.InputDevice
import com.android.systemui.CoreStartable
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
-import java.util.concurrent.Executor
import javax.inject.Inject
/**
@@ -40,16 +37,7 @@
private val inputManager: InputManager,
private val stylusUsiPowerUi: StylusUsiPowerUI,
private val featureFlags: FeatureFlags,
- @Background private val executor: Executor,
-) : CoreStartable, StylusManager.StylusCallback, InputManager.InputDeviceBatteryListener {
-
- override fun onStylusAdded(deviceId: Int) {
- val device = inputManager.getInputDevice(deviceId) ?: return
-
- if (!device.isExternal) {
- registerBatteryListener(deviceId)
- }
- }
+) : CoreStartable, StylusManager.StylusCallback, StylusManager.StylusBatteryCallback {
override fun onStylusBluetoothConnected(deviceId: Int, btAddress: String) {
stylusUsiPowerUi.refresh()
@@ -59,57 +47,30 @@
stylusUsiPowerUi.refresh()
}
- override fun onStylusRemoved(deviceId: Int) {
- val device = inputManager.getInputDevice(deviceId) ?: return
-
- if (!device.isExternal) {
- unregisterBatteryListener(deviceId)
- }
- }
-
- override fun onBatteryStateChanged(
+ override fun onStylusUsiBatteryStateChanged(
deviceId: Int,
eventTimeMillis: Long,
batteryState: BatteryState
) {
- if (batteryState.isPresent) {
- stylusUsiPowerUi.updateBatteryState(batteryState)
- }
- }
-
- private fun registerBatteryListener(deviceId: Int) {
- try {
- inputManager.addInputDeviceBatteryListener(deviceId, executor, this)
- } catch (e: SecurityException) {
- Log.e(TAG, "$e: Failed to register battery listener for $deviceId.")
- }
- }
-
- private fun unregisterBatteryListener(deviceId: Int) {
- try {
- inputManager.removeInputDeviceBatteryListener(deviceId, this)
- } catch (e: SecurityException) {
- Log.e(TAG, "$e: Failed to unregister battery listener for $deviceId.")
+ if (batteryState.isPresent && batteryState.capacity > 0f) {
+ stylusUsiPowerUi.updateBatteryState(deviceId, batteryState)
}
}
override fun start() {
if (!featureFlags.isEnabled(Flags.ENABLE_USI_BATTERY_NOTIFICATIONS)) return
- addBatteryListenerForInternalStyluses()
+ if (!hostDeviceSupportsStylusInput()) return
+ stylusUsiPowerUi.init()
stylusManager.registerCallback(this)
stylusManager.startListener()
}
- private fun addBatteryListenerForInternalStyluses() {
- // For most devices, an active stylus is represented by an internal InputDevice.
- // This InputDevice will be present in InputManager before CoreStartables run,
- // and will not be removed. In many cases, it reports the battery level of the stylus.
- inputManager.inputDeviceIds
+ private fun hostDeviceSupportsStylusInput(): Boolean {
+ return inputManager.inputDeviceIds
.asSequence()
.mapNotNull { inputManager.getInputDevice(it) }
- .filter { it.supportsSource(InputDevice.SOURCE_STYLUS) }
- .forEach { onStylusAdded(it.id) }
+ .any { it.supportsSource(InputDevice.SOURCE_STYLUS) && !it.isExternal }
}
companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt b/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt
index 70a5b36..8d5e01c 100644
--- a/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt
+++ b/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt
@@ -18,17 +18,21 @@
import android.Manifest
import android.app.PendingIntent
+import android.content.ActivityNotFoundException
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.hardware.BatteryState
import android.hardware.input.InputManager
+import android.os.Bundle
import android.os.Handler
import android.os.UserHandle
+import android.util.Log
import android.view.InputDevice
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
+import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.R
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
@@ -53,6 +57,7 @@
// These values must only be accessed on the handler.
private var batteryCapacity = 1.0f
private var suppressed = false
+ private var inputDeviceId: Int? = null
fun init() {
val filter =
@@ -87,10 +92,12 @@
}
}
- fun updateBatteryState(batteryState: BatteryState) {
+ fun updateBatteryState(deviceId: Int, batteryState: BatteryState) {
handler.post updateBattery@{
- if (batteryState.capacity == batteryCapacity) return@updateBattery
+ if (batteryState.capacity == batteryCapacity || batteryState.capacity <= 0f)
+ return@updateBattery
+ inputDeviceId = deviceId
batteryCapacity = batteryState.capacity
refresh()
}
@@ -123,13 +130,13 @@
.setSmallIcon(R.drawable.ic_power_low)
.setDeleteIntent(getPendingBroadcast(ACTION_DISMISSED_LOW_BATTERY))
.setContentIntent(getPendingBroadcast(ACTION_CLICKED_LOW_BATTERY))
- .setContentTitle(context.getString(R.string.stylus_battery_low))
- .setContentText(
+ .setContentTitle(
context.getString(
- R.string.battery_low_percent_format,
+ R.string.stylus_battery_low_percentage,
NumberFormat.getPercentInstance().format(batteryCapacity)
)
)
+ .setContentText(context.getString(R.string.stylus_battery_low_subtitle))
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setLocalOnly(true)
.setAutoCancel(true)
@@ -150,23 +157,41 @@
}
private fun getPendingBroadcast(action: String): PendingIntent? {
- return PendingIntent.getBroadcastAsUser(
+ return PendingIntent.getBroadcast(
context,
0,
- Intent(action),
+ Intent(action).setPackage(context.packageName),
PendingIntent.FLAG_IMMUTABLE,
- UserHandle.CURRENT
)
}
- private val receiver: BroadcastReceiver =
+ @VisibleForTesting
+ internal val receiver: BroadcastReceiver =
object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
when (intent.action) {
ACTION_DISMISSED_LOW_BATTERY -> updateSuppression(true)
ACTION_CLICKED_LOW_BATTERY -> {
updateSuppression(true)
- // TODO(b/261584943): open USI device details page
+ if (inputDeviceId == null) return
+
+ val args = Bundle()
+ args.putInt(KEY_DEVICE_INPUT_ID, inputDeviceId!!)
+ try {
+ context.startActivity(
+ Intent(ACTION_STYLUS_USI_DETAILS)
+ .putExtra(KEY_SETTINGS_FRAGMENT_ARGS, args)
+ .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ )
+ } catch (e: ActivityNotFoundException) {
+ // In the rare scenario where the Settings app manifest doesn't contain
+ // the USI details activity, ignore the intent.
+ Log.e(
+ StylusUsiPowerUI::class.java.simpleName,
+ "Cannot open USI details page."
+ )
+ }
}
}
}
@@ -177,9 +202,13 @@
// https://source.chromium.org/chromium/chromium/src/+/main:ash/system/power/peripheral_battery_notifier.cc;l=41
private const val LOW_BATTERY_THRESHOLD = 0.16f
- private val USI_NOTIFICATION_ID = R.string.stylus_battery_low
+ private val USI_NOTIFICATION_ID = R.string.stylus_battery_low_percentage
- private const val ACTION_DISMISSED_LOW_BATTERY = "StylusUsiPowerUI.dismiss"
- private const val ACTION_CLICKED_LOW_BATTERY = "StylusUsiPowerUI.click"
+ @VisibleForTesting const val ACTION_DISMISSED_LOW_BATTERY = "StylusUsiPowerUI.dismiss"
+ @VisibleForTesting const val ACTION_CLICKED_LOW_BATTERY = "StylusUsiPowerUI.click"
+ @VisibleForTesting
+ const val ACTION_STYLUS_USI_DETAILS = "com.android.settings.STYLUS_USI_DETAILS_SETTINGS"
+ @VisibleForTesting const val KEY_DEVICE_INPUT_ID = "device_input_id"
+ @VisibleForTesting const val KEY_SETTINGS_FRAGMENT_ARGS = ":settings:show_fragment_args"
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt
index 59ad24a..2709da3 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt
@@ -17,6 +17,9 @@
package com.android.systemui.unfold
import android.content.Context
+import android.hardware.devicestate.DeviceStateManager
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.keyguard.LifecycleScreenStatusProvider
import com.android.systemui.unfold.config.UnfoldTransitionConfig
import com.android.systemui.unfold.system.SystemUnfoldSharedModule
@@ -32,6 +35,7 @@
import dagger.Module
import dagger.Provides
import java.util.Optional
+import java.util.concurrent.Executor
import javax.inject.Named
import javax.inject.Singleton
@@ -40,6 +44,20 @@
@Provides @UnfoldTransitionATracePrefix fun tracingTagPrefix() = "systemui"
+ /** A globally available FoldStateListener that allows one to query the fold state. */
+ @Provides
+ @Singleton
+ fun providesFoldStateListener(
+ deviceStateManager: DeviceStateManager,
+ @Application context: Context,
+ @Main executor: Executor
+ ): DeviceStateManager.FoldStateListener {
+ val listener = DeviceStateManager.FoldStateListener(context)
+ deviceStateManager.registerCallback(executor, listener)
+
+ return listener
+ }
+
@Provides
@Singleton
fun providesFoldStateLoggingProvider(
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
index 84f6d91..075ef9d 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
@@ -405,6 +405,13 @@
}
@Test
+ public void onBouncerVisibilityChanged_resetsScale() {
+ mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.INVISIBLE);
+
+ verify(mView).resetScale();
+ }
+
+ @Test
public void onStartingToHide_sideFpsHintShown_sideFpsHintHidden() {
setupGetSecurityView();
setupConditionsToEnableSideFpsHint();
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
index 36ed669..1bbc199 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
@@ -49,6 +49,8 @@
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowInsets;
+import android.window.BackEvent;
+import android.window.OnBackAnimationCallback;
import androidx.constraintlayout.widget.ConstraintSet;
import androidx.test.filters.SmallTest;
@@ -357,6 +359,27 @@
assertThat(viewFlipperConstraint.layout.leftToLeft).isEqualTo(PARENT_ID);
}
+ @Test
+ public void testPlayBackAnimation() {
+ OnBackAnimationCallback backCallback = mKeyguardSecurityContainer.getBackCallback();
+ backCallback.onBackStarted(createBackEvent(0, 0));
+ mKeyguardSecurityContainer.getBackCallback().onBackProgressed(
+ createBackEvent(0, 1));
+ assertThat(mKeyguardSecurityContainer.getScaleX()).isEqualTo(
+ KeyguardSecurityContainer.MIN_BACK_SCALE);
+ assertThat(mKeyguardSecurityContainer.getScaleY()).isEqualTo(
+ KeyguardSecurityContainer.MIN_BACK_SCALE);
+
+ // reset scale
+ mKeyguardSecurityContainer.resetScale();
+ assertThat(mKeyguardSecurityContainer.getScaleX()).isEqualTo(1);
+ assertThat(mKeyguardSecurityContainer.getScaleY()).isEqualTo(1);
+ }
+
+ private BackEvent createBackEvent(float touchX, float progress) {
+ return new BackEvent(0, 0, progress, BackEvent.EDGE_LEFT);
+ }
+
private Configuration configuration(@Configuration.Orientation int orientation) {
Configuration config = new Configuration();
config.orientation = orientation;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index edf303e..87dd6a4 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -33,6 +33,9 @@
import static com.android.keyguard.KeyguardUpdateMonitor.DEFAULT_CANCEL_SIGNAL_TIMEOUT;
import static com.android.keyguard.KeyguardUpdateMonitor.HAL_POWER_PRESS_TIMEOUT;
import static com.android.keyguard.KeyguardUpdateMonitor.getCurrentUser;
+import static com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_CLOSED;
+import static com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_OPENED;
+import static com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_UNKNOWN;
import static com.google.common.truth.Truth.assertThat;
@@ -126,6 +129,7 @@
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
+import com.android.systemui.statusbar.policy.DevicePostureController;
import com.android.systemui.telephony.TelephonyListenerManager;
import com.android.systemui.util.settings.GlobalSettings;
import com.android.systemui.util.settings.SecureSettings;
@@ -195,6 +199,8 @@
@Mock
private DevicePolicyManager mDevicePolicyManager;
@Mock
+ private DevicePostureController mDevicePostureController;
+ @Mock
private IDreamManager mDreamManager;
@Mock
private KeyguardBypassController mKeyguardBypassController;
@@ -301,6 +307,7 @@
.thenReturn(new ServiceState());
when(mLockPatternUtils.getLockSettings()).thenReturn(mLockSettings);
when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(false);
+ when(mDevicePostureController.getDevicePosture()).thenReturn(DEVICE_POSTURE_UNKNOWN);
mMockitoSession = ExtendedMockito.mockitoSession()
.spyStatic(SubscriptionManager.class)
@@ -312,6 +319,9 @@
when(mUserTracker.getUserId()).thenReturn(mCurrentUserId);
ExtendedMockito.doReturn(mActivityService).when(ActivityManager::getService);
+ mContext.getOrCreateTestableResources().addOverride(
+ com.android.systemui.R.integer.config_face_auth_supported_posture,
+ DEVICE_POSTURE_UNKNOWN);
mFaceWakeUpTriggersConfig = new FaceWakeUpTriggersConfig(
mContext.getResources(),
mGlobalSettings,
@@ -2242,6 +2252,54 @@
eq(true));
}
+ @Test
+ public void testShouldListenForFace_withAuthSupportPostureConfig_returnsTrue()
+ throws RemoteException {
+ mKeyguardUpdateMonitor.mConfigFaceAuthSupportedPosture = DEVICE_POSTURE_CLOSED;
+ keyguardNotGoingAway();
+ bouncerFullyVisibleAndNotGoingToSleep();
+ currentUserIsPrimary();
+ currentUserDoesNotHaveTrust();
+ biometricsNotDisabledThroughDevicePolicyManager();
+ biometricsEnabledForCurrentUser();
+ userNotCurrentlySwitching();
+ supportsFaceDetection();
+
+ deviceInPostureStateOpened();
+ mTestableLooper.processAllMessages();
+ // Should not listen for face when posture state in DEVICE_POSTURE_OPENED
+ assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
+
+ deviceInPostureStateClosed();
+ mTestableLooper.processAllMessages();
+ // Should listen for face when posture state in DEVICE_POSTURE_CLOSED
+ assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue();
+ }
+
+ @Test
+ public void testShouldListenForFace_withoutAuthSupportPostureConfig_returnsTrue()
+ throws RemoteException {
+ mKeyguardUpdateMonitor.mConfigFaceAuthSupportedPosture = DEVICE_POSTURE_UNKNOWN;
+ keyguardNotGoingAway();
+ bouncerFullyVisibleAndNotGoingToSleep();
+ currentUserIsPrimary();
+ currentUserDoesNotHaveTrust();
+ biometricsNotDisabledThroughDevicePolicyManager();
+ biometricsEnabledForCurrentUser();
+ userNotCurrentlySwitching();
+ supportsFaceDetection();
+
+ deviceInPostureStateClosed();
+ mTestableLooper.processAllMessages();
+ // Whether device in any posture state, always listen for face
+ assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue();
+
+ deviceInPostureStateOpened();
+ mTestableLooper.processAllMessages();
+ // Whether device in any posture state, always listen for face
+ assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue();
+ }
+
private void userDeviceLockDown() {
when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
when(mStrongAuthTracker.getStrongAuthForUser(mCurrentUserId))
@@ -2321,6 +2379,14 @@
.onAuthenticationAcquired(FINGERPRINT_ACQUIRED_START);
}
+ private void deviceInPostureStateOpened() {
+ mKeyguardUpdateMonitor.mPostureCallback.onPostureChanged(DEVICE_POSTURE_OPENED);
+ }
+
+ private void deviceInPostureStateClosed() {
+ mKeyguardUpdateMonitor.mPostureCallback.onPostureChanged(DEVICE_POSTURE_CLOSED);
+ }
+
private void successfulFingerprintAuth() {
mKeyguardUpdateMonitor.mFingerprintAuthenticationCallback
.onAuthenticationSucceeded(
@@ -2462,7 +2528,8 @@
mPowerManager, mTrustManager, mSubscriptionManager, mUserManager,
mDreamManager, mDevicePolicyManager, mSensorPrivacyManager, mTelephonyManager,
mPackageManager, mFaceManager, mFingerprintManager, mBiometricManager,
- mFaceWakeUpTriggersConfig, Optional.of(mInteractiveToAuthProvider));
+ mFaceWakeUpTriggersConfig, mDevicePostureController,
+ Optional.of(mInteractiveToAuthProvider));
setStrongAuthTracker(KeyguardUpdateMonitorTest.this.mStrongAuthTracker);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt
index 7c1e384..cac4a0e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt
@@ -12,11 +12,13 @@
import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.WindowManager
+import android.widget.FrameLayout
import android.widget.LinearLayout
import androidx.test.filters.SmallTest
import com.android.internal.jank.InteractionJankMonitor
import com.android.internal.policy.DecorView
import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
import junit.framework.Assert.assertEquals
import junit.framework.Assert.assertFalse
import junit.framework.Assert.assertNotNull
@@ -205,25 +207,74 @@
verify(interactionJankMonitor).end(InteractionJankMonitor.CUJ_USER_DIALOG_OPEN)
}
+ @Test
+ fun testAnimationDoesNotChangeLaunchableViewVisibility_viewVisible() {
+ val touchSurface = createTouchSurface()
+
+ // View is VISIBLE when starting the animation.
+ runOnMainThreadAndWaitForIdleSync { touchSurface.visibility = View.VISIBLE }
+
+ // View is invisible while the dialog is shown.
+ val dialog = showDialogFromView(touchSurface)
+ assertThat(touchSurface.visibility).isEqualTo(View.INVISIBLE)
+
+ // View is visible again when the dialog is dismissed.
+ runOnMainThreadAndWaitForIdleSync { dialog.dismiss() }
+ assertThat(touchSurface.visibility).isEqualTo(View.VISIBLE)
+ }
+
+ @Test
+ fun testAnimationDoesNotChangeLaunchableViewVisibility_viewInvisible() {
+ val touchSurface = createTouchSurface()
+
+ // View is INVISIBLE when starting the animation.
+ runOnMainThreadAndWaitForIdleSync { touchSurface.visibility = View.INVISIBLE }
+
+ // View is INVISIBLE while the dialog is shown.
+ val dialog = showDialogFromView(touchSurface)
+ assertThat(touchSurface.visibility).isEqualTo(View.INVISIBLE)
+
+ // View is invisible like it was before showing the dialog.
+ runOnMainThreadAndWaitForIdleSync { dialog.dismiss() }
+ assertThat(touchSurface.visibility).isEqualTo(View.INVISIBLE)
+ }
+
+ @Test
+ fun testAnimationDoesNotChangeLaunchableViewVisibility_viewVisibleThenGone() {
+ val touchSurface = createTouchSurface()
+
+ // View is VISIBLE when starting the animation.
+ runOnMainThreadAndWaitForIdleSync { touchSurface.visibility = View.VISIBLE }
+
+ // View is INVISIBLE while the dialog is shown.
+ val dialog = showDialogFromView(touchSurface)
+ assertThat(touchSurface.visibility).isEqualTo(View.INVISIBLE)
+
+ // Some external call makes the View GONE. It remains INVISIBLE while the dialog is shown,
+ // as all visibility changes should be blocked.
+ runOnMainThreadAndWaitForIdleSync { touchSurface.visibility = View.GONE }
+ assertThat(touchSurface.visibility).isEqualTo(View.INVISIBLE)
+
+ // View is restored to GONE once the dialog is dismissed.
+ runOnMainThreadAndWaitForIdleSync { dialog.dismiss() }
+ assertThat(touchSurface.visibility).isEqualTo(View.GONE)
+ }
+
private fun createAndShowDialog(
animator: DialogLaunchAnimator = dialogLaunchAnimator,
): TestDialog {
val touchSurface = createTouchSurface()
- return runOnMainThreadAndWaitForIdleSync {
- val dialog = TestDialog(context)
- animator.showFromView(dialog, touchSurface)
- dialog
- }
+ return showDialogFromView(touchSurface, animator)
}
private fun createTouchSurface(): View {
return runOnMainThreadAndWaitForIdleSync {
val touchSurfaceRoot = LinearLayout(context)
- val touchSurface = View(context)
+ val touchSurface = TouchSurfaceView(context)
touchSurfaceRoot.addView(touchSurface)
// We need to attach the root to the window manager otherwise the exit animation will
- // be skipped
+ // be skipped.
ViewUtils.attachView(touchSurfaceRoot)
attachedViews.add(touchSurfaceRoot)
@@ -231,6 +282,17 @@
}
}
+ private fun showDialogFromView(
+ touchSurface: View,
+ animator: DialogLaunchAnimator = dialogLaunchAnimator,
+ ): TestDialog {
+ return runOnMainThreadAndWaitForIdleSync {
+ val dialog = TestDialog(context)
+ animator.showFromView(dialog, touchSurface)
+ dialog
+ }
+ }
+
private fun createDialogAndShowFromDialog(animateFrom: Dialog): TestDialog {
return runOnMainThreadAndWaitForIdleSync {
val dialog = TestDialog(context)
@@ -248,6 +310,22 @@
return result
}
+ private class TouchSurfaceView(context: Context) : FrameLayout(context), LaunchableView {
+ private val delegate =
+ LaunchableViewDelegate(
+ this,
+ superSetVisibility = { super.setVisibility(it) },
+ )
+
+ override fun setShouldBlockVisibilityChanges(block: Boolean) {
+ delegate.setShouldBlockVisibilityChanges(block)
+ }
+
+ override fun setVisibility(visibility: Int) {
+ delegate.setVisibility(visibility)
+ }
+ }
+
private class TestDialog(context: Context) : Dialog(context) {
companion object {
const val DIALOG_WIDTH = 100
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt
index 3b4f7e1..9060922 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt
@@ -31,9 +31,9 @@
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor
+import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.statusbar.StatusBarState
-import com.android.systemui.statusbar.phone.KeyguardBouncer
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.util.time.FakeSystemClock
import com.android.systemui.util.time.SystemClock
@@ -133,7 +133,7 @@
// WHEN the bouncer expansion is VISIBLE
val job = mController.listenForBouncerExpansion(this)
keyguardBouncerRepository.setPrimaryVisible(true)
- keyguardBouncerRepository.setPanelExpansion(KeyguardBouncer.EXPANSION_VISIBLE)
+ keyguardBouncerRepository.setPanelExpansion(KeyguardBouncerConstants.EXPANSION_VISIBLE)
yield()
// THEN UDFPS shouldPauseAuth == true
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/udfps/EllipseOverlapDetectorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/udfps/EllipseOverlapDetectorTest.kt
new file mode 100644
index 0000000..af46d9b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/udfps/EllipseOverlapDetectorTest.kt
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.biometrics.udfps
+
+import android.graphics.Point
+import android.graphics.Rect
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+import org.junit.runners.Parameterized.Parameters
+import org.mockito.Mockito.spy
+import org.mockito.Mockito.`when` as whenEver
+
+@SmallTest
+@RunWith(Parameterized::class)
+class EllipseOverlapDetectorTest(val testCase: TestCase) : SysuiTestCase() {
+ val underTest = spy(EllipseOverlapDetector(neededPoints = 1))
+
+ @Before
+ fun setUp() {
+ // Use one single center point for testing, required or total number of points may change
+ whenEver(underTest.calculateSensorPoints(SENSOR))
+ .thenReturn(listOf(Point(SENSOR.centerX(), SENSOR.centerY())))
+ }
+
+ @Test
+ fun isGoodOverlap() {
+ val touchData =
+ TOUCH_DATA.copy(
+ x = testCase.x.toFloat(),
+ y = testCase.y.toFloat(),
+ minor = testCase.minor,
+ major = testCase.major
+ )
+ val actual = underTest.isGoodOverlap(touchData, SENSOR)
+
+ assertThat(actual).isEqualTo(testCase.expected)
+ }
+
+ data class TestCase(
+ val x: Int,
+ val y: Int,
+ val minor: Float,
+ val major: Float,
+ val expected: Boolean
+ )
+
+ companion object {
+ @Parameters(name = "{0}")
+ @JvmStatic
+ fun data(): List<TestCase> =
+ listOf(
+ genTestCases(
+ innerXs = listOf(SENSOR.left, SENSOR.right, SENSOR.centerX()),
+ innerYs = listOf(SENSOR.top, SENSOR.bottom, SENSOR.centerY()),
+ outerXs = listOf(SENSOR.left - 1, SENSOR.right + 1),
+ outerYs = listOf(SENSOR.top - 1, SENSOR.bottom + 1),
+ minor = 300f,
+ major = 300f,
+ expected = true
+ ),
+ genTestCases(
+ innerXs = listOf(SENSOR.left, SENSOR.right),
+ innerYs = listOf(SENSOR.top, SENSOR.bottom),
+ outerXs = listOf(SENSOR.left - 1, SENSOR.right + 1),
+ outerYs = listOf(SENSOR.top - 1, SENSOR.bottom + 1),
+ minor = 100f,
+ major = 100f,
+ expected = false
+ )
+ )
+ .flatten()
+ }
+}
+
+/* Placeholder touch parameters. */
+private const val POINTER_ID = 42
+private const val NATIVE_MINOR = 2.71828f
+private const val NATIVE_MAJOR = 3.14f
+private const val ORIENTATION = 0f // used for perfect circles
+private const val TIME = 12345699L
+private const val GESTURE_START = 12345600L
+
+/* Template [NormalizedTouchData]. */
+private val TOUCH_DATA =
+ NormalizedTouchData(
+ POINTER_ID,
+ x = 0f,
+ y = 0f,
+ NATIVE_MINOR,
+ NATIVE_MAJOR,
+ ORIENTATION,
+ TIME,
+ GESTURE_START
+ )
+
+private val SENSOR = Rect(100 /* left */, 200 /* top */, 300 /* right */, 400 /* bottom */)
+
+private fun genTestCases(
+ innerXs: List<Int>,
+ innerYs: List<Int>,
+ outerXs: List<Int>,
+ outerYs: List<Int>,
+ minor: Float,
+ major: Float,
+ expected: Boolean
+): List<EllipseOverlapDetectorTest.TestCase> {
+ return (innerXs + outerXs).flatMap { x ->
+ (innerYs + outerYs).map { y ->
+ EllipseOverlapDetectorTest.TestCase(x, y, minor, major, expected)
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessorTest.kt
index 56043e30..34ddf79 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessorTest.kt
@@ -39,7 +39,8 @@
@Test
fun processTouch() {
- overlapDetector.shouldReturn = testCase.isGoodOverlap
+ overlapDetector.shouldReturn =
+ testCase.currentPointers.associate { pointer -> pointer.id to pointer.onSensor }
val actual =
underTest.processTouch(
@@ -56,7 +57,7 @@
data class TestCase(
val event: MotionEvent,
- val isGoodOverlap: Boolean,
+ val currentPointers: List<TestPointer>,
val previousPointerOnSensorId: Int,
val overlayParams: UdfpsOverlayParams,
val expected: TouchProcessorResult,
@@ -91,28 +92,21 @@
genPositiveTestCases(
motionEventAction = MotionEvent.ACTION_DOWN,
previousPointerOnSensorId = INVALID_POINTER_ID,
- isGoodOverlap = true,
+ currentPointers = listOf(TestPointer(id = POINTER_ID_1, onSensor = true)),
expectedInteractionEvent = InteractionEvent.DOWN,
- expectedPointerOnSensorId = POINTER_ID,
- ),
- genPositiveTestCases(
- motionEventAction = MotionEvent.ACTION_DOWN,
- previousPointerOnSensorId = POINTER_ID,
- isGoodOverlap = true,
- expectedInteractionEvent = InteractionEvent.DOWN,
- expectedPointerOnSensorId = POINTER_ID,
+ expectedPointerOnSensorId = POINTER_ID_1,
),
genPositiveTestCases(
motionEventAction = MotionEvent.ACTION_DOWN,
previousPointerOnSensorId = INVALID_POINTER_ID,
- isGoodOverlap = false,
+ currentPointers = listOf(TestPointer(id = POINTER_ID_1, onSensor = false)),
expectedInteractionEvent = InteractionEvent.UNCHANGED,
expectedPointerOnSensorId = INVALID_POINTER_ID,
),
genPositiveTestCases(
motionEventAction = MotionEvent.ACTION_DOWN,
- previousPointerOnSensorId = POINTER_ID,
- isGoodOverlap = false,
+ previousPointerOnSensorId = POINTER_ID_1,
+ currentPointers = listOf(TestPointer(id = POINTER_ID_1, onSensor = false)),
expectedInteractionEvent = InteractionEvent.UP,
expectedPointerOnSensorId = INVALID_POINTER_ID,
),
@@ -120,109 +114,226 @@
genPositiveTestCases(
motionEventAction = MotionEvent.ACTION_MOVE,
previousPointerOnSensorId = INVALID_POINTER_ID,
- isGoodOverlap = true,
+ currentPointers = listOf(TestPointer(id = POINTER_ID_1, onSensor = true)),
expectedInteractionEvent = InteractionEvent.DOWN,
- expectedPointerOnSensorId = POINTER_ID,
+ expectedPointerOnSensorId = POINTER_ID_1,
),
genPositiveTestCases(
motionEventAction = MotionEvent.ACTION_MOVE,
- previousPointerOnSensorId = POINTER_ID,
- isGoodOverlap = true,
+ previousPointerOnSensorId = POINTER_ID_1,
+ currentPointers = listOf(TestPointer(id = POINTER_ID_1, onSensor = true)),
expectedInteractionEvent = InteractionEvent.UNCHANGED,
- expectedPointerOnSensorId = POINTER_ID,
+ expectedPointerOnSensorId = POINTER_ID_1,
),
genPositiveTestCases(
motionEventAction = MotionEvent.ACTION_MOVE,
previousPointerOnSensorId = INVALID_POINTER_ID,
- isGoodOverlap = false,
+ currentPointers = listOf(TestPointer(id = POINTER_ID_1, onSensor = false)),
expectedInteractionEvent = InteractionEvent.UNCHANGED,
expectedPointerOnSensorId = INVALID_POINTER_ID,
),
genPositiveTestCases(
motionEventAction = MotionEvent.ACTION_MOVE,
- previousPointerOnSensorId = POINTER_ID,
- isGoodOverlap = false,
+ previousPointerOnSensorId = POINTER_ID_1,
+ currentPointers = listOf(TestPointer(id = POINTER_ID_1, onSensor = false)),
expectedInteractionEvent = InteractionEvent.UP,
expectedPointerOnSensorId = INVALID_POINTER_ID,
),
+ genPositiveTestCases(
+ motionEventAction = MotionEvent.ACTION_MOVE,
+ previousPointerOnSensorId = INVALID_POINTER_ID,
+ currentPointers =
+ listOf(
+ TestPointer(id = POINTER_ID_1, onSensor = false),
+ TestPointer(id = POINTER_ID_2, onSensor = true)
+ ),
+ expectedInteractionEvent = InteractionEvent.DOWN,
+ expectedPointerOnSensorId = POINTER_ID_2,
+ ),
+ genPositiveTestCases(
+ motionEventAction = MotionEvent.ACTION_MOVE,
+ previousPointerOnSensorId = POINTER_ID_1,
+ currentPointers =
+ listOf(
+ TestPointer(id = POINTER_ID_1, onSensor = false),
+ TestPointer(id = POINTER_ID_2, onSensor = true)
+ ),
+ expectedInteractionEvent = InteractionEvent.UNCHANGED,
+ expectedPointerOnSensorId = POINTER_ID_2,
+ ),
// MotionEvent.ACTION_UP
genPositiveTestCases(
motionEventAction = MotionEvent.ACTION_UP,
previousPointerOnSensorId = INVALID_POINTER_ID,
- isGoodOverlap = true,
+ currentPointers = listOf(TestPointer(id = POINTER_ID_1, onSensor = true)),
expectedInteractionEvent = InteractionEvent.UP,
expectedPointerOnSensorId = INVALID_POINTER_ID,
),
genPositiveTestCases(
motionEventAction = MotionEvent.ACTION_UP,
- previousPointerOnSensorId = POINTER_ID,
- isGoodOverlap = true,
+ previousPointerOnSensorId = POINTER_ID_1,
+ currentPointers = listOf(TestPointer(id = POINTER_ID_1, onSensor = true)),
expectedInteractionEvent = InteractionEvent.UP,
expectedPointerOnSensorId = INVALID_POINTER_ID,
),
genPositiveTestCases(
motionEventAction = MotionEvent.ACTION_UP,
previousPointerOnSensorId = INVALID_POINTER_ID,
- isGoodOverlap = false,
+ currentPointers = listOf(TestPointer(id = POINTER_ID_1, onSensor = false)),
expectedInteractionEvent = InteractionEvent.UNCHANGED,
expectedPointerOnSensorId = INVALID_POINTER_ID,
),
- genPositiveTestCases(
- motionEventAction = MotionEvent.ACTION_UP,
- previousPointerOnSensorId = POINTER_ID,
- isGoodOverlap = false,
- expectedInteractionEvent = InteractionEvent.UP,
- expectedPointerOnSensorId = INVALID_POINTER_ID,
- ),
// MotionEvent.ACTION_CANCEL
genPositiveTestCases(
motionEventAction = MotionEvent.ACTION_CANCEL,
previousPointerOnSensorId = INVALID_POINTER_ID,
- isGoodOverlap = true,
+ currentPointers = listOf(TestPointer(id = POINTER_ID_1, onSensor = true)),
expectedInteractionEvent = InteractionEvent.CANCEL,
expectedPointerOnSensorId = INVALID_POINTER_ID,
),
genPositiveTestCases(
motionEventAction = MotionEvent.ACTION_CANCEL,
- previousPointerOnSensorId = POINTER_ID,
- isGoodOverlap = true,
+ previousPointerOnSensorId = POINTER_ID_1,
+ currentPointers = listOf(TestPointer(id = POINTER_ID_1, onSensor = true)),
expectedInteractionEvent = InteractionEvent.CANCEL,
expectedPointerOnSensorId = INVALID_POINTER_ID,
),
genPositiveTestCases(
motionEventAction = MotionEvent.ACTION_CANCEL,
previousPointerOnSensorId = INVALID_POINTER_ID,
- isGoodOverlap = false,
+ currentPointers = listOf(TestPointer(id = POINTER_ID_1, onSensor = false)),
expectedInteractionEvent = InteractionEvent.CANCEL,
expectedPointerOnSensorId = INVALID_POINTER_ID,
),
genPositiveTestCases(
motionEventAction = MotionEvent.ACTION_CANCEL,
- previousPointerOnSensorId = POINTER_ID,
- isGoodOverlap = false,
+ previousPointerOnSensorId = POINTER_ID_1,
+ currentPointers = listOf(TestPointer(id = POINTER_ID_1, onSensor = false)),
expectedInteractionEvent = InteractionEvent.CANCEL,
expectedPointerOnSensorId = INVALID_POINTER_ID,
),
+ // MotionEvent.ACTION_POINTER_DOWN
+ genPositiveTestCases(
+ motionEventAction =
+ MotionEvent.ACTION_POINTER_DOWN +
+ (1 shl MotionEvent.ACTION_POINTER_INDEX_SHIFT),
+ previousPointerOnSensorId = INVALID_POINTER_ID,
+ currentPointers =
+ listOf(
+ TestPointer(id = POINTER_ID_1, onSensor = true),
+ TestPointer(id = POINTER_ID_2, onSensor = false)
+ ),
+ expectedInteractionEvent = InteractionEvent.DOWN,
+ expectedPointerOnSensorId = POINTER_ID_1,
+ ),
+ genPositiveTestCases(
+ motionEventAction =
+ MotionEvent.ACTION_POINTER_DOWN +
+ (1 shl MotionEvent.ACTION_POINTER_INDEX_SHIFT),
+ previousPointerOnSensorId = INVALID_POINTER_ID,
+ currentPointers =
+ listOf(
+ TestPointer(id = POINTER_ID_1, onSensor = false),
+ TestPointer(id = POINTER_ID_2, onSensor = true)
+ ),
+ expectedInteractionEvent = InteractionEvent.DOWN,
+ expectedPointerOnSensorId = POINTER_ID_2
+ ),
+ genPositiveTestCases(
+ motionEventAction =
+ MotionEvent.ACTION_POINTER_DOWN +
+ (1 shl MotionEvent.ACTION_POINTER_INDEX_SHIFT),
+ previousPointerOnSensorId = POINTER_ID_1,
+ currentPointers =
+ listOf(
+ TestPointer(id = POINTER_ID_1, onSensor = true),
+ TestPointer(id = POINTER_ID_2, onSensor = false)
+ ),
+ expectedInteractionEvent = InteractionEvent.UNCHANGED,
+ expectedPointerOnSensorId = POINTER_ID_1,
+ ),
+ // MotionEvent.ACTION_POINTER_UP
+ genPositiveTestCases(
+ motionEventAction =
+ MotionEvent.ACTION_POINTER_UP +
+ (1 shl MotionEvent.ACTION_POINTER_INDEX_SHIFT),
+ previousPointerOnSensorId = INVALID_POINTER_ID,
+ currentPointers =
+ listOf(
+ TestPointer(id = POINTER_ID_1, onSensor = false),
+ TestPointer(id = POINTER_ID_2, onSensor = false)
+ ),
+ expectedInteractionEvent = InteractionEvent.UNCHANGED,
+ expectedPointerOnSensorId = INVALID_POINTER_ID
+ ),
+ genPositiveTestCases(
+ motionEventAction =
+ MotionEvent.ACTION_POINTER_UP +
+ (1 shl MotionEvent.ACTION_POINTER_INDEX_SHIFT),
+ previousPointerOnSensorId = POINTER_ID_2,
+ currentPointers =
+ listOf(
+ TestPointer(id = POINTER_ID_1, onSensor = false),
+ TestPointer(id = POINTER_ID_2, onSensor = true)
+ ),
+ expectedInteractionEvent = InteractionEvent.UP,
+ expectedPointerOnSensorId = INVALID_POINTER_ID
+ ),
+ genPositiveTestCases(
+ motionEventAction = MotionEvent.ACTION_POINTER_UP,
+ previousPointerOnSensorId = POINTER_ID_1,
+ currentPointers =
+ listOf(
+ TestPointer(id = POINTER_ID_1, onSensor = true),
+ TestPointer(id = POINTER_ID_2, onSensor = false)
+ ),
+ expectedInteractionEvent = InteractionEvent.UP,
+ expectedPointerOnSensorId = INVALID_POINTER_ID
+ ),
+ genPositiveTestCases(
+ motionEventAction =
+ MotionEvent.ACTION_POINTER_UP +
+ (1 shl MotionEvent.ACTION_POINTER_INDEX_SHIFT),
+ previousPointerOnSensorId = POINTER_ID_1,
+ currentPointers =
+ listOf(
+ TestPointer(id = POINTER_ID_1, onSensor = true),
+ TestPointer(id = POINTER_ID_2, onSensor = false)
+ ),
+ expectedInteractionEvent = InteractionEvent.UNCHANGED,
+ expectedPointerOnSensorId = POINTER_ID_1
+ ),
+ genPositiveTestCases(
+ motionEventAction = MotionEvent.ACTION_POINTER_UP,
+ previousPointerOnSensorId = POINTER_ID_2,
+ currentPointers =
+ listOf(
+ TestPointer(id = POINTER_ID_1, onSensor = false),
+ TestPointer(id = POINTER_ID_2, onSensor = true)
+ ),
+ expectedInteractionEvent = InteractionEvent.UNCHANGED,
+ expectedPointerOnSensorId = POINTER_ID_2
+ )
)
.flatten() +
listOf(
- // Unsupported MotionEvent actions.
- genTestCasesForUnsupportedAction(MotionEvent.ACTION_POINTER_DOWN),
- genTestCasesForUnsupportedAction(MotionEvent.ACTION_POINTER_UP),
genTestCasesForUnsupportedAction(MotionEvent.ACTION_HOVER_ENTER),
genTestCasesForUnsupportedAction(MotionEvent.ACTION_HOVER_MOVE),
- genTestCasesForUnsupportedAction(MotionEvent.ACTION_HOVER_EXIT),
+ genTestCasesForUnsupportedAction(MotionEvent.ACTION_HOVER_EXIT)
)
.flatten()
}
}
+data class TestPointer(val id: Int, val onSensor: Boolean)
+
/* Display dimensions in native resolution and natural orientation. */
private const val ROTATION_0_NATIVE_DISPLAY_WIDTH = 400
private const val ROTATION_0_NATIVE_DISPLAY_HEIGHT = 600
/* Placeholder touch parameters. */
-private const val POINTER_ID = 42
+private const val POINTER_ID_1 = 42
+private const val POINTER_ID_2 = 43
private const val NATIVE_MINOR = 2.71828f
private const val NATIVE_MAJOR = 3.14f
private const val ORIENTATION = 1.2345f
@@ -325,7 +436,7 @@
private val MOTION_EVENT =
obtainMotionEvent(
action = 0,
- pointerId = POINTER_ID,
+ pointerId = POINTER_ID_1,
x = 0f,
y = 0f,
minor = 0f,
@@ -338,7 +449,7 @@
/* Template [NormalizedTouchData]. */
private val NORMALIZED_TOUCH_DATA =
NormalizedTouchData(
- POINTER_ID,
+ POINTER_ID_1,
x = 0f,
y = 0f,
NATIVE_MINOR,
@@ -384,7 +495,7 @@
private fun genPositiveTestCases(
motionEventAction: Int,
previousPointerOnSensorId: Int,
- isGoodOverlap: Boolean,
+ currentPointers: List<TestPointer>,
expectedInteractionEvent: InteractionEvent,
expectedPointerOnSensorId: Int
): List<SinglePointerTouchProcessorTest.TestCase> {
@@ -399,22 +510,47 @@
return scaleFactors.flatMap { scaleFactor ->
orientations.map { orientation ->
val overlayParams = orientation.toOverlayParams(scaleFactor)
- val nativeX = orientation.getNativeX(isGoodOverlap)
- val nativeY = orientation.getNativeY(isGoodOverlap)
+
+ val pointerProperties =
+ currentPointers
+ .map { pointer ->
+ val pp = MotionEvent.PointerProperties()
+ pp.id = pointer.id
+ pp
+ }
+ .toList()
+
+ val pointerCoords =
+ currentPointers
+ .map { pointer ->
+ val pc = MotionEvent.PointerCoords()
+ pc.x = orientation.getNativeX(pointer.onSensor) * scaleFactor
+ pc.y = orientation.getNativeY(pointer.onSensor) * scaleFactor
+ pc.touchMinor = NATIVE_MINOR * scaleFactor
+ pc.touchMajor = NATIVE_MAJOR * scaleFactor
+ pc.orientation = orientation.nativeOrientation
+ pc
+ }
+ .toList()
+
val event =
MOTION_EVENT.copy(
action = motionEventAction,
- x = nativeX * scaleFactor,
- y = nativeY * scaleFactor,
- minor = NATIVE_MINOR * scaleFactor,
- major = NATIVE_MAJOR * scaleFactor,
- orientation = orientation.nativeOrientation
+ pointerProperties = pointerProperties,
+ pointerCoords = pointerCoords
)
+
val expectedTouchData =
- NORMALIZED_TOUCH_DATA.copy(
- x = ROTATION_0_INPUTS.getNativeX(isGoodOverlap),
- y = ROTATION_0_INPUTS.getNativeY(isGoodOverlap),
- )
+ if (expectedPointerOnSensorId != INVALID_POINTER_ID) {
+ NORMALIZED_TOUCH_DATA.copy(
+ pointerId = expectedPointerOnSensorId,
+ x = ROTATION_0_INPUTS.getNativeX(isWithinSensor = true),
+ y = ROTATION_0_INPUTS.getNativeY(isWithinSensor = true)
+ )
+ } else {
+ NormalizedTouchData()
+ }
+
val expected =
TouchProcessorResult.ProcessedTouch(
event = expectedInteractionEvent,
@@ -423,7 +559,7 @@
)
SinglePointerTouchProcessorTest.TestCase(
event = event,
- isGoodOverlap = isGoodOverlap,
+ currentPointers = currentPointers,
previousPointerOnSensorId = previousPointerOnSensorId,
overlayParams = overlayParams,
expected = expected,
@@ -436,7 +572,7 @@
motionEventAction: Int
): List<SinglePointerTouchProcessorTest.TestCase> {
val isGoodOverlap = true
- val previousPointerOnSensorIds = listOf(INVALID_POINTER_ID, POINTER_ID)
+ val previousPointerOnSensorIds = listOf(INVALID_POINTER_ID, POINTER_ID_1)
return previousPointerOnSensorIds.map { previousPointerOnSensorId ->
val overlayParams = ROTATION_0_INPUTS.toOverlayParams(scaleFactor = 1f)
val nativeX = ROTATION_0_INPUTS.getNativeX(isGoodOverlap)
@@ -451,7 +587,7 @@
)
SinglePointerTouchProcessorTest.TestCase(
event = event,
- isGoodOverlap = isGoodOverlap,
+ currentPointers = listOf(TestPointer(id = POINTER_ID_1, onSensor = isGoodOverlap)),
previousPointerOnSensorId = previousPointerOnSensorId,
overlayParams = overlayParams,
expected = TouchProcessorResult.Failure(),
@@ -478,13 +614,23 @@
pc.touchMinor = minor
pc.touchMajor = major
pc.orientation = orientation
+ return obtainMotionEvent(action, arrayOf(pp), arrayOf(pc), time, gestureStart)
+}
+
+private fun obtainMotionEvent(
+ action: Int,
+ pointerProperties: Array<MotionEvent.PointerProperties>,
+ pointerCoords: Array<MotionEvent.PointerCoords>,
+ time: Long,
+ gestureStart: Long,
+): MotionEvent {
return MotionEvent.obtain(
gestureStart /* downTime */,
time /* eventTime */,
action /* action */,
- 1 /* pointerCount */,
- arrayOf(pp) /* pointerProperties */,
- arrayOf(pc) /* pointerCoords */,
+ pointerCoords.size /* pointerCount */,
+ pointerProperties /* pointerProperties */,
+ pointerCoords /* pointerCoords */,
0 /* metaState */,
0 /* buttonState */,
1f /* xPrecision */,
@@ -508,4 +654,19 @@
gestureStart: Long = this.downTime,
) = obtainMotionEvent(action, pointerId, x, y, minor, major, orientation, time, gestureStart)
+private fun MotionEvent.copy(
+ action: Int = this.action,
+ pointerProperties: List<MotionEvent.PointerProperties>,
+ pointerCoords: List<MotionEvent.PointerCoords>,
+ time: Long = this.eventTime,
+ gestureStart: Long = this.downTime
+) =
+ obtainMotionEvent(
+ action,
+ pointerProperties.toTypedArray(),
+ pointerCoords.toTypedArray(),
+ time,
+ gestureStart
+ )
+
private fun Rect.scaled(scaleFactor: Float) = Rect(this).apply { scale(scaleFactor) }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java
index 0fadc13..e4df754 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java
@@ -106,6 +106,7 @@
mClassifiers.add(mClassifierB);
when(mFalsingDataProvider.getRecentMotionEvents()).thenReturn(mMotionEventList);
when(mKeyguardStateController.isShowing()).thenReturn(true);
+ when(mFalsingDataProvider.isFolded()).thenReturn(true);
mBrightLineFalsingManager = new BrightLineFalsingManager(mFalsingDataProvider,
mMetricsLogger, mClassifiers, mSingleTapClassfier, mLongTapClassifier,
mDoubleTapClassifier, mHistoryTracker, mKeyguardStateController,
@@ -121,6 +122,7 @@
mGestureFinalizedListener = gestureCompleteListenerCaptor.getValue();
mFakeFeatureFlags.set(Flags.FALSING_FOR_LONG_TAPS, true);
mFakeFeatureFlags.set(Flags.MEDIA_FALSING_PENALTY, true);
+ mFakeFeatureFlags.set(Flags.FALSING_OFF_FOR_UNFOLDED, true);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java
index 4281ee0..ae38eb6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java
@@ -89,25 +89,27 @@
mClassifiers.add(mClassifierA);
when(mFalsingDataProvider.getRecentMotionEvents()).thenReturn(mMotionEventList);
when(mKeyguardStateController.isShowing()).thenReturn(true);
+ when(mFalsingDataProvider.isFolded()).thenReturn(true);
mBrightLineFalsingManager = new BrightLineFalsingManager(mFalsingDataProvider,
mMetricsLogger, mClassifiers, mSingleTapClassifier, mLongTapClassifier,
mDoubleTapClassifier, mHistoryTracker, mKeyguardStateController,
mAccessibilityManager, false, mFakeFeatureFlags);
mFakeFeatureFlags.set(Flags.FALSING_FOR_LONG_TAPS, true);
+ mFakeFeatureFlags.set(Flags.FALSING_OFF_FOR_UNFOLDED, true);
}
@Test
public void testA11yDisablesGesture() {
- assertThat(mBrightLineFalsingManager.isFalseTap(1)).isTrue();
+ assertThat(mBrightLineFalsingManager.isFalseTouch(Classifier.GENERIC)).isTrue();
when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(true);
- assertThat(mBrightLineFalsingManager.isFalseTap(1)).isFalse();
+ assertThat(mBrightLineFalsingManager.isFalseTouch(Classifier.GENERIC)).isFalse();
}
@Test
public void testA11yDisablesTap() {
- assertThat(mBrightLineFalsingManager.isFalseTouch(Classifier.GENERIC)).isTrue();
+ assertThat(mBrightLineFalsingManager.isFalseTap(1)).isTrue();
when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(true);
- assertThat(mBrightLineFalsingManager.isFalseTouch(Classifier.GENERIC)).isFalse();
+ assertThat(mBrightLineFalsingManager.isFalseTap(1)).isFalse();
}
@@ -179,4 +181,11 @@
when(mFalsingDataProvider.isA11yAction()).thenReturn(true);
assertThat(mBrightLineFalsingManager.isFalseTap(1)).isFalse();
}
+
+ @Test
+ public void testSkipUnfolded() {
+ assertThat(mBrightLineFalsingManager.isFalseTouch(Classifier.GENERIC)).isTrue();
+ when(mFalsingDataProvider.isFolded()).thenReturn(false);
+ assertThat(mBrightLineFalsingManager.isFalseTouch(Classifier.GENERIC)).isFalse();
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/ClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/ClassifierTest.java
index 5fa7214..94cf384 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/ClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/ClassifierTest.java
@@ -16,6 +16,7 @@
package com.android.systemui.classifier;
+import android.hardware.devicestate.DeviceStateManager.FoldStateListener;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
@@ -38,6 +39,7 @@
private float mOffsetY = 0;
@Mock
private BatteryController mBatteryController;
+ private FoldStateListener mFoldStateListener = new FoldStateListener(mContext);
private final DockManagerFake mDockManager = new DockManagerFake();
public void setup() {
@@ -47,7 +49,8 @@
displayMetrics.ydpi = 100;
displayMetrics.widthPixels = 1000;
displayMetrics.heightPixels = 1000;
- mDataProvider = new FalsingDataProvider(displayMetrics, mBatteryController, mDockManager);
+ mDataProvider = new FalsingDataProvider(
+ displayMetrics, mBatteryController, mFoldStateListener, mDockManager);
}
@After
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java
index d315c2d..c451a1e7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java
@@ -24,6 +24,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.hardware.devicestate.DeviceStateManager.FoldStateListener;
import android.testing.AndroidTestingRunner;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
@@ -50,6 +51,8 @@
private FalsingDataProvider mDataProvider;
@Mock
private BatteryController mBatteryController;
+ @Mock
+ private FoldStateListener mFoldStateListener;
private final DockManagerFake mDockManager = new DockManagerFake();
@Before
@@ -61,7 +64,8 @@
displayMetrics.ydpi = 100;
displayMetrics.widthPixels = 1000;
displayMetrics.heightPixels = 1000;
- mDataProvider = new FalsingDataProvider(displayMetrics, mBatteryController, mDockManager);
+ mDataProvider = new FalsingDataProvider(
+ displayMetrics, mBatteryController, mFoldStateListener, mDockManager);
}
@After
@@ -316,4 +320,16 @@
mDataProvider.onA11yAction();
assertThat(mDataProvider.isA11yAction()).isTrue();
}
+
+ @Test
+ public void test_FoldedState_Folded() {
+ when(mFoldStateListener.getFolded()).thenReturn(true);
+ assertThat(mDataProvider.isFolded()).isTrue();
+ }
+
+ @Test
+ public void test_FoldedState_Unfolded() {
+ when(mFoldStateListener.getFolded()).thenReturn(false);
+ assertThat(mDataProvider.isFolded()).isFalse();
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/compose/ComposeInitializerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/compose/ComposeInitializerTest.kt
new file mode 100644
index 0000000..3e6cc3b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/compose/ComposeInitializerTest.kt
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.compose
+
+import android.content.Context
+import android.testing.AndroidTestingRunner
+import android.testing.ViewUtils
+import android.widget.FrameLayout
+import androidx.compose.ui.platform.ComposeView
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class ComposeInitializerTest : SysuiTestCase() {
+ @Test
+ fun testCanAddComposeViewInInitializedWindow() {
+ if (!ComposeFacade.isComposeAvailable()) {
+ return
+ }
+
+ val root = TestWindowRoot(context)
+ try {
+ runOnMainThreadAndWaitForIdleSync { ViewUtils.attachView(root) }
+ assertThat(root.isAttachedToWindow).isTrue()
+
+ runOnMainThreadAndWaitForIdleSync { root.addView(ComposeView(context)) }
+ } finally {
+ runOnMainThreadAndWaitForIdleSync { ViewUtils.detachView(root) }
+ }
+ }
+
+ private fun runOnMainThreadAndWaitForIdleSync(f: () -> Unit) {
+ mContext.mainExecutor.execute(f)
+ waitForIdleSync()
+ }
+
+ class TestWindowRoot(context: Context) : FrameLayout(context) {
+ override fun onAttachedToWindow() {
+ super.onAttachedToWindow()
+ ComposeFacade.composeInitializer().onAttachedToWindow(this)
+ }
+
+ override fun onDetachedFromWindow() {
+ super.onDetachedFromWindow()
+ ComposeFacade.composeInitializer().onDetachedFromWindow(this)
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsBindingControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsBindingControllerImplTest.kt
index 0a81c38..ebbe096 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsBindingControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsBindingControllerImplTest.kt
@@ -269,6 +269,14 @@
}
@Test
+ fun testBindServiceForPanel() {
+ controller.bindServiceForPanel(TEST_COMPONENT_NAME_1)
+ executor.runAllReady()
+
+ verify(providers[0]).bindServiceForPanel()
+ }
+
+ @Test
fun testSubscribe() {
val controlInfo1 = ControlInfo("id_1", "", "", DeviceTypes.TYPE_UNKNOWN)
val controlInfo2 = ControlInfo("id_2", "", "", DeviceTypes.TYPE_UNKNOWN)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
index 1b34706..25f471b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
@@ -919,6 +919,12 @@
.getFile(ControlsFavoritePersistenceWrapper.FILE_NAME, context.user.identifier)
assertThat(userStructure.file).isNotNull()
}
+
+ @Test
+ fun testBindForPanel() {
+ controller.bindComponentForPanel(TEST_COMPONENT)
+ verify(bindingController).bindServiceForPanel(TEST_COMPONENT)
+ }
}
private class DidRunRunnable() : Runnable {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt
index af3f24a..da548f7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt
@@ -105,6 +105,22 @@
}
@Test
+ fun testBindForPanel() {
+ manager.bindServiceForPanel()
+ executor.runAllReady()
+ assertTrue(context.isBound(componentName))
+ }
+
+ @Test
+ fun testUnbindPanelIsUnbound() {
+ manager.bindServiceForPanel()
+ executor.runAllReady()
+ manager.unbindService()
+ executor.runAllReady()
+ assertFalse(context.isBound(componentName))
+ }
+
+ @Test
fun testNullBinding() {
val mockContext = mock(Context::class.java)
lateinit var serviceConnection: ServiceConnection
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt
index d172c9a..edc6882 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt
@@ -229,6 +229,15 @@
}
@Test
+ fun testPanelBindsForPanel() {
+ val panel = SelectedItem.PanelItem("App name", ComponentName("pkg", "cls"))
+ setUpPanel(panel)
+
+ underTest.show(parent, {}, context)
+ verify(controlsController).bindComponentForPanel(panel.componentName)
+ }
+
+ @Test
fun testPanelCallsTaskViewFactoryCreate() {
mockLayoutInflater()
val panel = SelectedItem.PanelItem("App name", ComponentName("pkg", "cls"))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java
index 4bd53c0..f64179d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java
@@ -41,11 +41,11 @@
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants;
import com.android.systemui.shade.ShadeExpansionChangeEvent;
import com.android.systemui.shared.system.InputChannelCompat;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.phone.CentralSurfaces;
-import com.android.systemui.statusbar.phone.KeyguardBouncer;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.wm.shell.animation.FlingAnimationUtils;
@@ -302,12 +302,13 @@
final float velocityY = -1;
swipeToPosition(swipeUpPercentage, Direction.UP, velocityY);
- verify(mValueAnimatorCreator).create(eq(expansion), eq(KeyguardBouncer.EXPANSION_HIDDEN));
+ verify(mValueAnimatorCreator).create(eq(expansion),
+ eq(KeyguardBouncerConstants.EXPANSION_HIDDEN));
verify(mValueAnimator, never()).addListener(any());
verify(mFlingAnimationUtilsClosing).apply(eq(mValueAnimator),
eq(SCREEN_HEIGHT_PX * expansion),
- eq(SCREEN_HEIGHT_PX * KeyguardBouncer.EXPANSION_HIDDEN),
+ eq(SCREEN_HEIGHT_PX * KeyguardBouncerConstants.EXPANSION_HIDDEN),
eq(velocityY), eq((float) SCREEN_HEIGHT_PX));
verify(mValueAnimator).start();
verify(mUiEventLogger, never()).log(any());
@@ -324,7 +325,8 @@
final float velocityY = 1;
swipeToPosition(swipeUpPercentage, Direction.UP, velocityY);
- verify(mValueAnimatorCreator).create(eq(expansion), eq(KeyguardBouncer.EXPANSION_VISIBLE));
+ verify(mValueAnimatorCreator).create(eq(expansion),
+ eq(KeyguardBouncerConstants.EXPANSION_VISIBLE));
ArgumentCaptor<AnimatorListenerAdapter> endAnimationListenerCaptor =
ArgumentCaptor.forClass(AnimatorListenerAdapter.class);
@@ -332,7 +334,7 @@
AnimatorListenerAdapter endAnimationListener = endAnimationListenerCaptor.getValue();
verify(mFlingAnimationUtils).apply(eq(mValueAnimator), eq(SCREEN_HEIGHT_PX * expansion),
- eq(SCREEN_HEIGHT_PX * KeyguardBouncer.EXPANSION_VISIBLE),
+ eq(SCREEN_HEIGHT_PX * KeyguardBouncerConstants.EXPANSION_VISIBLE),
eq(velocityY), eq((float) SCREEN_HEIGHT_PX));
verify(mValueAnimator).start();
verify(mUiEventLogger).log(BouncerSwipeTouchHandler.DreamEvent.DREAM_SWIPED);
@@ -355,12 +357,12 @@
swipeToPosition(swipeDownPercentage, Direction.DOWN, velocityY);
verify(mValueAnimatorCreator).create(eq(swipeDownPercentage),
- eq(KeyguardBouncer.EXPANSION_VISIBLE));
+ eq(KeyguardBouncerConstants.EXPANSION_VISIBLE));
verify(mValueAnimator, never()).addListener(any());
verify(mFlingAnimationUtils).apply(eq(mValueAnimator),
eq(SCREEN_HEIGHT_PX * swipeDownPercentage),
- eq(SCREEN_HEIGHT_PX * KeyguardBouncer.EXPANSION_VISIBLE),
+ eq(SCREEN_HEIGHT_PX * KeyguardBouncerConstants.EXPANSION_VISIBLE),
eq(velocityY), eq((float) SCREEN_HEIGHT_PX));
verify(mValueAnimator).start();
verify(mUiEventLogger, never()).log(any());
@@ -381,12 +383,12 @@
swipeToPosition(swipeDownPercentage, Direction.DOWN, velocityY);
verify(mValueAnimatorCreator).create(eq(swipeDownPercentage),
- eq(KeyguardBouncer.EXPANSION_HIDDEN));
+ eq(KeyguardBouncerConstants.EXPANSION_HIDDEN));
verify(mValueAnimator, never()).addListener(any());
verify(mFlingAnimationUtilsClosing).apply(eq(mValueAnimator),
eq(SCREEN_HEIGHT_PX * swipeDownPercentage),
- eq(SCREEN_HEIGHT_PX * KeyguardBouncer.EXPANSION_HIDDEN),
+ eq(SCREEN_HEIGHT_PX * KeyguardBouncerConstants.EXPANSION_HIDDEN),
eq(velocityY), eq((float) SCREEN_HEIGHT_PX));
verify(mValueAnimator).start();
verify(mUiEventLogger, never()).log(any());
@@ -405,7 +407,8 @@
final float velocityY = -1;
swipeToPosition(swipeUpPercentage, Direction.UP, velocityY);
- verify(mValueAnimatorCreator).create(eq(expansion), eq(KeyguardBouncer.EXPANSION_VISIBLE));
+ verify(mValueAnimatorCreator).create(eq(expansion),
+ eq(KeyguardBouncerConstants.EXPANSION_VISIBLE));
ArgumentCaptor<AnimatorListenerAdapter> endAnimationListenerCaptor =
ArgumentCaptor.forClass(AnimatorListenerAdapter.class);
@@ -413,7 +416,7 @@
AnimatorListenerAdapter endAnimationListener = endAnimationListenerCaptor.getValue();
verify(mFlingAnimationUtils).apply(eq(mValueAnimator), eq(SCREEN_HEIGHT_PX * expansion),
- eq(SCREEN_HEIGHT_PX * KeyguardBouncer.EXPANSION_VISIBLE),
+ eq(SCREEN_HEIGHT_PX * KeyguardBouncerConstants.EXPANSION_VISIBLE),
eq(velocityY), eq((float) SCREEN_HEIGHT_PX));
verify(mValueAnimator).start();
verify(mUiEventLogger).log(BouncerSwipeTouchHandler.DreamEvent.DREAM_SWIPED);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index 59e4655..7c20e3c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -29,6 +29,7 @@
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -485,6 +486,38 @@
assertTrue(mViewMediator.isShowingAndNotOccluded());
}
+ @Test
+ @TestableLooper.RunWithLooper(setAsMainLooper = true)
+ public void testDoKeyguardWhileInteractive_resets() {
+ mViewMediator.setShowingLocked(true);
+ when(mKeyguardStateController.isShowing()).thenReturn(true);
+ TestableLooper.get(this).processAllMessages();
+
+ when(mPowerManager.isInteractive()).thenReturn(true);
+
+ mViewMediator.onSystemReady();
+ TestableLooper.get(this).processAllMessages();
+
+ assertTrue(mViewMediator.isShowingAndNotOccluded());
+ verify(mStatusBarKeyguardViewManager).reset(anyBoolean());
+ }
+
+ @Test
+ @TestableLooper.RunWithLooper(setAsMainLooper = true)
+ public void testDoKeyguardWhileNotInteractive_showsInsteadOfResetting() {
+ mViewMediator.setShowingLocked(true);
+ when(mKeyguardStateController.isShowing()).thenReturn(true);
+ TestableLooper.get(this).processAllMessages();
+
+ when(mPowerManager.isInteractive()).thenReturn(false);
+
+ mViewMediator.onSystemReady();
+ TestableLooper.get(this).processAllMessages();
+
+ assertTrue(mViewMediator.isShowingAndNotOccluded());
+ verify(mStatusBarKeyguardViewManager, never()).reset(anyBoolean());
+ }
+
private void createAndStartViewMediator() {
mViewMediator = new KeyguardViewMediator(
mContext,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/WakefulnessLifecycleTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/WakefulnessLifecycleTest.java
index f32d76b..39a453d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/WakefulnessLifecycleTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/WakefulnessLifecycleTest.java
@@ -30,6 +30,7 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.util.time.FakeSystemClock;
import org.junit.Before;
import org.junit.Test;
@@ -51,7 +52,12 @@
public void setUp() throws Exception {
mWallpaperManager = mock(IWallpaperManager.class);
mWakefulness =
- new WakefulnessLifecycle(mContext, mWallpaperManager, mock(DumpManager.class));
+ new WakefulnessLifecycle(
+ mContext,
+ mWallpaperManager,
+ new FakeSystemClock(),
+ mock(DumpManager.class)
+ );
mWakefulnessObserver = mock(WakefulnessLifecycle.Observer.class);
mWakefulness.addObserver(mWakefulnessObserver);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfigTest.kt
index 7c10108..15b85de 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfigTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfigTest.kt
@@ -38,6 +38,7 @@
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.settings.FakeSettings
+import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestDispatcher
@@ -83,169 +84,205 @@
settings = FakeSettings()
- underTest = DoNotDisturbQuickAffordanceConfig(
- context,
- zenModeController,
- settings,
- userTracker,
- testDispatcher,
- conditionUri,
- enableZenModeDialog,
- )
+ underTest =
+ DoNotDisturbQuickAffordanceConfig(
+ context,
+ zenModeController,
+ settings,
+ userTracker,
+ testDispatcher,
+ conditionUri,
+ enableZenModeDialog,
+ )
}
@Test
- fun `dnd not available - picker state hidden`() = testScope.runTest {
- //given
- whenever(zenModeController.isZenAvailable).thenReturn(false)
+ fun `dnd not available - picker state hidden`() =
+ testScope.runTest {
+ // given
+ whenever(zenModeController.isZenAvailable).thenReturn(false)
- //when
- val result = underTest.getPickerScreenState()
+ // when
+ val result = underTest.getPickerScreenState()
- //then
- assertEquals(KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice, result)
- }
+ // then
+ assertEquals(
+ KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice,
+ result
+ )
+ }
@Test
- fun `dnd available - picker state visible`() = testScope.runTest {
- //given
- whenever(zenModeController.isZenAvailable).thenReturn(true)
+ fun `dnd available - picker state visible`() =
+ testScope.runTest {
+ // given
+ whenever(zenModeController.isZenAvailable).thenReturn(true)
- //when
- val result = underTest.getPickerScreenState()
+ // when
+ val result = underTest.getPickerScreenState()
- //then
- assertEquals(KeyguardQuickAffordanceConfig.PickerScreenState.Default, result)
- }
+ // then
+ assertThat(result)
+ .isInstanceOf(KeyguardQuickAffordanceConfig.PickerScreenState.Default::class.java)
+ val defaultPickerState =
+ result as KeyguardQuickAffordanceConfig.PickerScreenState.Default
+ assertThat(defaultPickerState.configureIntent).isNotNull()
+ assertThat(defaultPickerState.configureIntent?.action)
+ .isEqualTo(Settings.ACTION_ZEN_MODE_SETTINGS)
+ }
@Test
- fun `onTriggered - dnd mode is not ZEN_MODE_OFF - set to ZEN_MODE_OFF`() = testScope.runTest {
- //given
- whenever(zenModeController.isZenAvailable).thenReturn(true)
- whenever(zenModeController.zen).thenReturn(-1)
- settings.putInt(Settings.Secure.ZEN_DURATION, -2)
- collectLastValue(underTest.lockScreenState)
- runCurrent()
+ fun `onTriggered - dnd mode is not ZEN_MODE_OFF - set to ZEN_MODE_OFF`() =
+ testScope.runTest {
+ // given
+ whenever(zenModeController.isZenAvailable).thenReturn(true)
+ whenever(zenModeController.zen).thenReturn(-1)
+ settings.putInt(Settings.Secure.ZEN_DURATION, -2)
+ collectLastValue(underTest.lockScreenState)
+ runCurrent()
- //when
- val result = underTest.onTriggered(null)
- verify(zenModeController).setZen(spyZenMode.capture(), spyConditionId.capture(), eq(DoNotDisturbQuickAffordanceConfig.TAG))
+ // when
+ val result = underTest.onTriggered(null)
+ verify(zenModeController)
+ .setZen(
+ spyZenMode.capture(),
+ spyConditionId.capture(),
+ eq(DoNotDisturbQuickAffordanceConfig.TAG)
+ )
- //then
- assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled, result)
- assertEquals(ZEN_MODE_OFF, spyZenMode.value)
- assertNull(spyConditionId.value)
- }
+ // then
+ assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled, result)
+ assertEquals(ZEN_MODE_OFF, spyZenMode.value)
+ assertNull(spyConditionId.value)
+ }
@Test
- fun `onTriggered - dnd mode is ZEN_MODE_OFF - setting is FOREVER - set zen with no condition`() = testScope.runTest {
- //given
- whenever(zenModeController.isZenAvailable).thenReturn(true)
- whenever(zenModeController.zen).thenReturn(ZEN_MODE_OFF)
- settings.putInt(Settings.Secure.ZEN_DURATION, ZEN_DURATION_FOREVER)
- collectLastValue(underTest.lockScreenState)
- runCurrent()
+ fun `onTriggered - dnd mode is ZEN_MODE_OFF - setting FOREVER - set zen without condition`() =
+ testScope.runTest {
+ // given
+ whenever(zenModeController.isZenAvailable).thenReturn(true)
+ whenever(zenModeController.zen).thenReturn(ZEN_MODE_OFF)
+ settings.putInt(Settings.Secure.ZEN_DURATION, ZEN_DURATION_FOREVER)
+ collectLastValue(underTest.lockScreenState)
+ runCurrent()
- //when
- val result = underTest.onTriggered(null)
- verify(zenModeController).setZen(spyZenMode.capture(), spyConditionId.capture(), eq(DoNotDisturbQuickAffordanceConfig.TAG))
+ // when
+ val result = underTest.onTriggered(null)
+ verify(zenModeController)
+ .setZen(
+ spyZenMode.capture(),
+ spyConditionId.capture(),
+ eq(DoNotDisturbQuickAffordanceConfig.TAG)
+ )
- //then
- assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled, result)
- assertEquals(ZEN_MODE_IMPORTANT_INTERRUPTIONS, spyZenMode.value)
- assertNull(spyConditionId.value)
- }
+ // then
+ assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled, result)
+ assertEquals(ZEN_MODE_IMPORTANT_INTERRUPTIONS, spyZenMode.value)
+ assertNull(spyConditionId.value)
+ }
@Test
- fun `onTriggered - dnd mode is ZEN_MODE_OFF - setting is not FOREVER or PROMPT - set zen with condition`() = testScope.runTest {
- //given
- whenever(zenModeController.isZenAvailable).thenReturn(true)
- whenever(zenModeController.zen).thenReturn(ZEN_MODE_OFF)
- settings.putInt(Settings.Secure.ZEN_DURATION, -900)
- collectLastValue(underTest.lockScreenState)
- runCurrent()
+ fun `onTriggered - dnd ZEN_MODE_OFF - setting not FOREVER or PROMPT - zen with condition`() =
+ testScope.runTest {
+ // given
+ whenever(zenModeController.isZenAvailable).thenReturn(true)
+ whenever(zenModeController.zen).thenReturn(ZEN_MODE_OFF)
+ settings.putInt(Settings.Secure.ZEN_DURATION, -900)
+ collectLastValue(underTest.lockScreenState)
+ runCurrent()
- //when
- val result = underTest.onTriggered(null)
- verify(zenModeController).setZen(spyZenMode.capture(), spyConditionId.capture(), eq(DoNotDisturbQuickAffordanceConfig.TAG))
+ // when
+ val result = underTest.onTriggered(null)
+ verify(zenModeController)
+ .setZen(
+ spyZenMode.capture(),
+ spyConditionId.capture(),
+ eq(DoNotDisturbQuickAffordanceConfig.TAG)
+ )
- //then
- assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled, result)
- assertEquals(ZEN_MODE_IMPORTANT_INTERRUPTIONS, spyZenMode.value)
- assertEquals(conditionUri, spyConditionId.value)
- }
+ // then
+ assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled, result)
+ assertEquals(ZEN_MODE_IMPORTANT_INTERRUPTIONS, spyZenMode.value)
+ assertEquals(conditionUri, spyConditionId.value)
+ }
@Test
- fun `onTriggered - dnd mode is ZEN_MODE_OFF - setting is PROMPT - show dialog`() = testScope.runTest {
- //given
- val expandable: Expandable = mock()
- whenever(zenModeController.isZenAvailable).thenReturn(true)
- whenever(zenModeController.zen).thenReturn(ZEN_MODE_OFF)
- settings.putInt(Settings.Secure.ZEN_DURATION, ZEN_DURATION_PROMPT)
- whenever(enableZenModeDialog.createDialog()).thenReturn(mock())
- collectLastValue(underTest.lockScreenState)
- runCurrent()
+ fun `onTriggered - dnd mode is ZEN_MODE_OFF - setting is PROMPT - show dialog`() =
+ testScope.runTest {
+ // given
+ val expandable: Expandable = mock()
+ whenever(zenModeController.isZenAvailable).thenReturn(true)
+ whenever(zenModeController.zen).thenReturn(ZEN_MODE_OFF)
+ settings.putInt(Settings.Secure.ZEN_DURATION, ZEN_DURATION_PROMPT)
+ whenever(enableZenModeDialog.createDialog()).thenReturn(mock())
+ collectLastValue(underTest.lockScreenState)
+ runCurrent()
- //when
- val result = underTest.onTriggered(expandable)
+ // when
+ val result = underTest.onTriggered(expandable)
- //then
- assertTrue(result is KeyguardQuickAffordanceConfig.OnTriggeredResult.ShowDialog)
- assertEquals(expandable, (result as KeyguardQuickAffordanceConfig.OnTriggeredResult.ShowDialog).expandable)
- }
+ // then
+ assertTrue(result is KeyguardQuickAffordanceConfig.OnTriggeredResult.ShowDialog)
+ assertEquals(
+ expandable,
+ (result as KeyguardQuickAffordanceConfig.OnTriggeredResult.ShowDialog).expandable
+ )
+ }
@Test
- fun `lockScreenState - dndAvailable starts as true - changes to false - State moves to Hidden`() = testScope.runTest {
- //given
- whenever(zenModeController.isZenAvailable).thenReturn(true)
- val callbackCaptor: ArgumentCaptor<ZenModeController.Callback> = argumentCaptor()
- val valueSnapshot = collectLastValue(underTest.lockScreenState)
- val secondLastValue = valueSnapshot()
- verify(zenModeController).addCallback(callbackCaptor.capture())
+ fun `lockScreenState - dndAvailable starts as true - change to false - State is Hidden`() =
+ testScope.runTest {
+ // given
+ whenever(zenModeController.isZenAvailable).thenReturn(true)
+ val callbackCaptor: ArgumentCaptor<ZenModeController.Callback> = argumentCaptor()
+ val valueSnapshot = collectLastValue(underTest.lockScreenState)
+ val secondLastValue = valueSnapshot()
+ verify(zenModeController).addCallback(callbackCaptor.capture())
- //when
- callbackCaptor.value.onZenAvailableChanged(false)
- val lastValue = valueSnapshot()
+ // when
+ callbackCaptor.value.onZenAvailableChanged(false)
+ val lastValue = valueSnapshot()
- //then
- assertTrue(secondLastValue is KeyguardQuickAffordanceConfig.LockScreenState.Visible)
- assertTrue(lastValue is KeyguardQuickAffordanceConfig.LockScreenState.Hidden)
- }
+ // then
+ assertTrue(secondLastValue is KeyguardQuickAffordanceConfig.LockScreenState.Visible)
+ assertTrue(lastValue is KeyguardQuickAffordanceConfig.LockScreenState.Hidden)
+ }
@Test
- fun `lockScreenState - dndMode starts as ZEN_MODE_OFF - changes to not OFF - State moves to Visible`() = testScope.runTest {
- //given
- whenever(zenModeController.isZenAvailable).thenReturn(true)
- whenever(zenModeController.zen).thenReturn(ZEN_MODE_OFF)
- val valueSnapshot = collectLastValue(underTest.lockScreenState)
- val secondLastValue = valueSnapshot()
- val callbackCaptor: ArgumentCaptor<ZenModeController.Callback> = argumentCaptor()
- verify(zenModeController).addCallback(callbackCaptor.capture())
+ fun `lockScreenState - dndMode starts as ZEN_MODE_OFF - change to not OFF - State Visible`() =
+ testScope.runTest {
+ // given
+ whenever(zenModeController.isZenAvailable).thenReturn(true)
+ whenever(zenModeController.zen).thenReturn(ZEN_MODE_OFF)
+ val valueSnapshot = collectLastValue(underTest.lockScreenState)
+ val secondLastValue = valueSnapshot()
+ val callbackCaptor: ArgumentCaptor<ZenModeController.Callback> = argumentCaptor()
+ verify(zenModeController).addCallback(callbackCaptor.capture())
- //when
- callbackCaptor.value.onZenChanged(ZEN_MODE_IMPORTANT_INTERRUPTIONS)
- val lastValue = valueSnapshot()
+ // when
+ callbackCaptor.value.onZenChanged(ZEN_MODE_IMPORTANT_INTERRUPTIONS)
+ val lastValue = valueSnapshot()
- //then
- assertEquals(
- KeyguardQuickAffordanceConfig.LockScreenState.Visible(
- Icon.Resource(
- R.drawable.qs_dnd_icon_off,
- ContentDescription.Resource(R.string.dnd_is_off)
+ // then
+ assertEquals(
+ KeyguardQuickAffordanceConfig.LockScreenState.Visible(
+ Icon.Resource(
+ R.drawable.qs_dnd_icon_off,
+ ContentDescription.Resource(R.string.dnd_is_off)
+ ),
+ ActivationState.Inactive
),
- ActivationState.Inactive
- ),
- secondLastValue,
- )
- assertEquals(
- KeyguardQuickAffordanceConfig.LockScreenState.Visible(
- Icon.Resource(
- R.drawable.qs_dnd_icon_on,
- ContentDescription.Resource(R.string.dnd_is_on)
+ secondLastValue,
+ )
+ assertEquals(
+ KeyguardQuickAffordanceConfig.LockScreenState.Visible(
+ Icon.Resource(
+ R.drawable.qs_dnd_icon_on,
+ ContentDescription.Resource(R.string.dnd_is_on)
+ ),
+ ActivationState.Active
),
- ActivationState.Active
- ),
- lastValue,
- )
- }
-}
\ No newline at end of file
+ lastValue,
+ )
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfigTest.kt
index 6255980..9d2ddff 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfigTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfigTest.kt
@@ -141,7 +141,7 @@
whenever(controller.isAbleToOpenCameraApp).thenReturn(true)
assertThat(underTest.getPickerScreenState())
- .isEqualTo(KeyguardQuickAffordanceConfig.PickerScreenState.Default)
+ .isEqualTo(KeyguardQuickAffordanceConfig.PickerScreenState.Default())
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt
index d875dd9..ca44fa18 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt
@@ -159,7 +159,7 @@
setUpState()
assertThat(underTest.getPickerScreenState())
- .isEqualTo(KeyguardQuickAffordanceConfig.PickerScreenState.Default)
+ .isEqualTo(KeyguardQuickAffordanceConfig.PickerScreenState.Default())
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
index be712f6..f997d18 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
@@ -24,6 +24,7 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.AuthController
import com.android.systemui.common.shared.model.Position
+import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.doze.DozeHost
import com.android.systemui.doze.DozeMachine
import com.android.systemui.doze.DozeTransitionCallback
@@ -38,14 +39,17 @@
import com.android.systemui.keyguard.shared.model.WakefulnessState
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.phone.BiometricUnlockController
+import com.android.systemui.statusbar.phone.DozeParameters
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.mockito.withArgCaptor
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
@@ -68,6 +72,7 @@
@Mock private lateinit var authController: AuthController
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
@Mock private lateinit var dreamOverlayCallbackController: DreamOverlayCallbackController
+ @Mock private lateinit var dozeParameters: DozeParameters
private lateinit var underTest: KeyguardRepositoryImpl
@@ -84,6 +89,7 @@
keyguardStateController,
keyguardUpdateMonitor,
dozeTransitionListener,
+ dozeParameters,
authController,
dreamOverlayCallbackController,
)
@@ -170,6 +176,26 @@
}
@Test
+ fun isAodAvailable() = runTest {
+ val flow = underTest.isAodAvailable
+ var isAodAvailable = collectLastValue(flow)
+ runCurrent()
+
+ val callback =
+ withArgCaptor<DozeParameters.Callback> { verify(dozeParameters).addCallback(capture()) }
+
+ whenever(dozeParameters.getAlwaysOn()).thenReturn(false)
+ callback.onAlwaysOnChange()
+ assertThat(isAodAvailable()).isEqualTo(false)
+
+ whenever(dozeParameters.getAlwaysOn()).thenReturn(true)
+ callback.onAlwaysOnChange()
+ assertThat(isAodAvailable()).isEqualTo(true)
+
+ flow.onCompletion { verify(dozeParameters).removeCallback(callback) }
+ }
+
+ @Test
fun isKeyguardOccluded() =
runTest(UnconfinedTestDispatcher()) {
whenever(keyguardStateController.isOccluded).thenReturn(false)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt
index f8f2a56..32cec09 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt
@@ -168,6 +168,25 @@
assertThat(wtfHandler.failed).isTrue()
}
+ @Test
+ fun `Attempt to manually update transition after CANCELED state throws exception`() {
+ val uuid =
+ underTest.startTransition(
+ TransitionInfo(
+ ownerName = OWNER_NAME,
+ from = AOD,
+ to = LOCKSCREEN,
+ animator = null,
+ )
+ )
+
+ checkNotNull(uuid).let {
+ underTest.updateTransition(it, 0.2f, TransitionState.CANCELED)
+ underTest.updateTransition(it, 0.5f, TransitionState.RUNNING)
+ }
+ assertThat(wtfHandler.failed).isTrue()
+ }
+
private fun listWithStep(
step: BigDecimal,
start: BigDecimal = BigDecimal.ZERO,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
index 754adfd..a1b6d47 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
@@ -38,6 +38,7 @@
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.cancelChildren
import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -71,6 +72,10 @@
private lateinit var fromLockscreenTransitionInteractor: FromLockscreenTransitionInteractor
private lateinit var fromDreamingTransitionInteractor: FromDreamingTransitionInteractor
+ private lateinit var fromDozingTransitionInteractor: FromDozingTransitionInteractor
+ private lateinit var fromOccludedTransitionInteractor: FromOccludedTransitionInteractor
+ private lateinit var fromGoneTransitionInteractor: FromGoneTransitionInteractor
+ private lateinit var fromAodTransitionInteractor: FromAodTransitionInteractor
@Before
fun setUp() {
@@ -102,6 +107,42 @@
keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
)
fromDreamingTransitionInteractor.start()
+
+ fromAodTransitionInteractor =
+ FromAodTransitionInteractor(
+ scope = testScope,
+ keyguardInteractor = KeyguardInteractor(keyguardRepository, commandQueue),
+ keyguardTransitionRepository = mockTransitionRepository,
+ keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
+ )
+ fromAodTransitionInteractor.start()
+
+ fromGoneTransitionInteractor =
+ FromGoneTransitionInteractor(
+ scope = testScope,
+ keyguardInteractor = KeyguardInteractor(keyguardRepository, commandQueue),
+ keyguardTransitionRepository = mockTransitionRepository,
+ keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
+ )
+ fromGoneTransitionInteractor.start()
+
+ fromDozingTransitionInteractor =
+ FromDozingTransitionInteractor(
+ scope = testScope,
+ keyguardInteractor = KeyguardInteractor(keyguardRepository, commandQueue),
+ keyguardTransitionRepository = mockTransitionRepository,
+ keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
+ )
+ fromDozingTransitionInteractor.start()
+
+ fromOccludedTransitionInteractor =
+ FromOccludedTransitionInteractor(
+ scope = testScope,
+ keyguardInteractor = KeyguardInteractor(keyguardRepository, commandQueue),
+ keyguardTransitionRepository = mockTransitionRepository,
+ keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
+ )
+ fromOccludedTransitionInteractor.start()
}
@Test
@@ -137,7 +178,7 @@
keyguardRepository.setDreamingWithOverlay(false)
// AND occluded has stopped
keyguardRepository.setKeyguardOccluded(false)
- runCurrent()
+ advanceUntilIdle()
val info =
withArgCaptor<TransitionInfo> {
@@ -192,6 +233,332 @@
coroutineContext.cancelChildren()
}
+ @Test
+ fun `OCCLUDED to DOZING`() =
+ testScope.runTest {
+ // GIVEN a device with AOD not available
+ keyguardRepository.setAodAvailable(false)
+ runCurrent()
+
+ // GIVEN a prior transition has run to OCCLUDED
+ runner.startTransition(
+ testScope,
+ TransitionInfo(
+ ownerName = "",
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.OCCLUDED,
+ animator =
+ ValueAnimator().apply {
+ duration = 10
+ interpolator = Interpolators.LINEAR
+ },
+ )
+ )
+ runCurrent()
+ reset(mockTransitionRepository)
+
+ // WHEN the device begins to sleep
+ keyguardRepository.setWakefulnessModel(startingToSleep())
+ runCurrent()
+
+ val info =
+ withArgCaptor<TransitionInfo> {
+ verify(mockTransitionRepository).startTransition(capture())
+ }
+ // THEN a transition to DOZING should occur
+ assertThat(info.ownerName).isEqualTo("FromOccludedTransitionInteractor")
+ assertThat(info.from).isEqualTo(KeyguardState.OCCLUDED)
+ assertThat(info.to).isEqualTo(KeyguardState.DOZING)
+ assertThat(info.animator).isNotNull()
+
+ coroutineContext.cancelChildren()
+ }
+
+ @Test
+ fun `OCCLUDED to AOD`() =
+ testScope.runTest {
+ // GIVEN a device with AOD available
+ keyguardRepository.setAodAvailable(true)
+ runCurrent()
+
+ // GIVEN a prior transition has run to OCCLUDED
+ runner.startTransition(
+ testScope,
+ TransitionInfo(
+ ownerName = "",
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.OCCLUDED,
+ animator =
+ ValueAnimator().apply {
+ duration = 10
+ interpolator = Interpolators.LINEAR
+ },
+ )
+ )
+ runCurrent()
+ reset(mockTransitionRepository)
+
+ // WHEN the device begins to sleep
+ keyguardRepository.setWakefulnessModel(startingToSleep())
+ runCurrent()
+
+ val info =
+ withArgCaptor<TransitionInfo> {
+ verify(mockTransitionRepository).startTransition(capture())
+ }
+ // THEN a transition to DOZING should occur
+ assertThat(info.ownerName).isEqualTo("FromOccludedTransitionInteractor")
+ assertThat(info.from).isEqualTo(KeyguardState.OCCLUDED)
+ assertThat(info.to).isEqualTo(KeyguardState.AOD)
+ assertThat(info.animator).isNotNull()
+
+ coroutineContext.cancelChildren()
+ }
+
+ @Test
+ fun `LOCKSCREEN to DOZING`() =
+ testScope.runTest {
+ // GIVEN a device with AOD not available
+ keyguardRepository.setAodAvailable(false)
+ runCurrent()
+
+ // GIVEN a prior transition has run to LOCKSCREEN
+ runner.startTransition(
+ testScope,
+ TransitionInfo(
+ ownerName = "",
+ from = KeyguardState.GONE,
+ to = KeyguardState.LOCKSCREEN,
+ animator =
+ ValueAnimator().apply {
+ duration = 10
+ interpolator = Interpolators.LINEAR
+ },
+ )
+ )
+ runCurrent()
+ reset(mockTransitionRepository)
+
+ // WHEN the device begins to sleep
+ keyguardRepository.setWakefulnessModel(startingToSleep())
+ runCurrent()
+
+ val info =
+ withArgCaptor<TransitionInfo> {
+ verify(mockTransitionRepository).startTransition(capture())
+ }
+ // THEN a transition to DOZING should occur
+ assertThat(info.ownerName).isEqualTo("FromLockscreenTransitionInteractor")
+ assertThat(info.from).isEqualTo(KeyguardState.LOCKSCREEN)
+ assertThat(info.to).isEqualTo(KeyguardState.DOZING)
+ assertThat(info.animator).isNotNull()
+
+ coroutineContext.cancelChildren()
+ }
+
+ @Test
+ fun `LOCKSCREEN to AOD`() =
+ testScope.runTest {
+ // GIVEN a device with AOD available
+ keyguardRepository.setAodAvailable(true)
+ runCurrent()
+
+ // GIVEN a prior transition has run to LOCKSCREEN
+ runner.startTransition(
+ testScope,
+ TransitionInfo(
+ ownerName = "",
+ from = KeyguardState.GONE,
+ to = KeyguardState.LOCKSCREEN,
+ animator =
+ ValueAnimator().apply {
+ duration = 10
+ interpolator = Interpolators.LINEAR
+ },
+ )
+ )
+ runCurrent()
+ reset(mockTransitionRepository)
+
+ // WHEN the device begins to sleep
+ keyguardRepository.setWakefulnessModel(startingToSleep())
+ runCurrent()
+
+ val info =
+ withArgCaptor<TransitionInfo> {
+ verify(mockTransitionRepository).startTransition(capture())
+ }
+ // THEN a transition to DOZING should occur
+ assertThat(info.ownerName).isEqualTo("FromLockscreenTransitionInteractor")
+ assertThat(info.from).isEqualTo(KeyguardState.LOCKSCREEN)
+ assertThat(info.to).isEqualTo(KeyguardState.AOD)
+ assertThat(info.animator).isNotNull()
+
+ coroutineContext.cancelChildren()
+ }
+
+ @Test
+ fun `DOZING to LOCKSCREEN`() =
+ testScope.runTest {
+ // GIVEN a prior transition has run to DOZING
+ runner.startTransition(
+ testScope,
+ TransitionInfo(
+ ownerName = "",
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.DOZING,
+ animator =
+ ValueAnimator().apply {
+ duration = 10
+ interpolator = Interpolators.LINEAR
+ },
+ )
+ )
+ runCurrent()
+ reset(mockTransitionRepository)
+
+ // WHEN the device begins to wake
+ keyguardRepository.setWakefulnessModel(startingToWake())
+ runCurrent()
+
+ val info =
+ withArgCaptor<TransitionInfo> {
+ verify(mockTransitionRepository).startTransition(capture())
+ }
+ // THEN a transition to DOZING should occur
+ assertThat(info.ownerName).isEqualTo("FromDozingTransitionInteractor")
+ assertThat(info.from).isEqualTo(KeyguardState.DOZING)
+ assertThat(info.to).isEqualTo(KeyguardState.LOCKSCREEN)
+ assertThat(info.animator).isNotNull()
+
+ coroutineContext.cancelChildren()
+ }
+
+ @Test
+ fun `GONE to DOZING`() =
+ testScope.runTest {
+ // GIVEN a device with AOD not available
+ keyguardRepository.setAodAvailable(false)
+ runCurrent()
+
+ // GIVEN a prior transition has run to GONE
+ runner.startTransition(
+ testScope,
+ TransitionInfo(
+ ownerName = "",
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.GONE,
+ animator =
+ ValueAnimator().apply {
+ duration = 10
+ interpolator = Interpolators.LINEAR
+ },
+ )
+ )
+ runCurrent()
+ reset(mockTransitionRepository)
+
+ // WHEN the device begins to sleep
+ keyguardRepository.setWakefulnessModel(startingToSleep())
+ runCurrent()
+
+ val info =
+ withArgCaptor<TransitionInfo> {
+ verify(mockTransitionRepository).startTransition(capture())
+ }
+ // THEN a transition to DOZING should occur
+ assertThat(info.ownerName).isEqualTo("FromGoneTransitionInteractor")
+ assertThat(info.from).isEqualTo(KeyguardState.GONE)
+ assertThat(info.to).isEqualTo(KeyguardState.DOZING)
+ assertThat(info.animator).isNotNull()
+
+ coroutineContext.cancelChildren()
+ }
+
+ @Test
+ fun `GONE to AOD`() =
+ testScope.runTest {
+ // GIVEN a device with AOD available
+ keyguardRepository.setAodAvailable(true)
+ runCurrent()
+
+ // GIVEN a prior transition has run to GONE
+ runner.startTransition(
+ testScope,
+ TransitionInfo(
+ ownerName = "",
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.GONE,
+ animator =
+ ValueAnimator().apply {
+ duration = 10
+ interpolator = Interpolators.LINEAR
+ },
+ )
+ )
+ runCurrent()
+ reset(mockTransitionRepository)
+
+ // WHEN the device begins to sleep
+ keyguardRepository.setWakefulnessModel(startingToSleep())
+ runCurrent()
+
+ val info =
+ withArgCaptor<TransitionInfo> {
+ verify(mockTransitionRepository).startTransition(capture())
+ }
+ // THEN a transition to AOD should occur
+ assertThat(info.ownerName).isEqualTo("FromGoneTransitionInteractor")
+ assertThat(info.from).isEqualTo(KeyguardState.GONE)
+ assertThat(info.to).isEqualTo(KeyguardState.AOD)
+ assertThat(info.animator).isNotNull()
+
+ coroutineContext.cancelChildren()
+ }
+
+ @Test
+ fun `GONE to DREAMING`() =
+ testScope.runTest {
+ // GIVEN a device that is not dreaming or dozing
+ keyguardRepository.setDreamingWithOverlay(false)
+ keyguardRepository.setDozeTransitionModel(
+ DozeTransitionModel(from = DozeStateModel.DOZE, to = DozeStateModel.FINISH)
+ )
+ runCurrent()
+
+ // GIVEN a prior transition has run to GONE
+ runner.startTransition(
+ testScope,
+ TransitionInfo(
+ ownerName = "",
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.GONE,
+ animator =
+ ValueAnimator().apply {
+ duration = 10
+ interpolator = Interpolators.LINEAR
+ },
+ )
+ )
+ reset(mockTransitionRepository)
+
+ // WHEN the device begins to dream
+ keyguardRepository.setDreamingWithOverlay(true)
+ advanceUntilIdle()
+
+ val info =
+ withArgCaptor<TransitionInfo> {
+ verify(mockTransitionRepository).startTransition(capture())
+ }
+ // THEN a transition to DREAMING should occur
+ assertThat(info.ownerName).isEqualTo("FromGoneTransitionInteractor")
+ assertThat(info.from).isEqualTo(KeyguardState.GONE)
+ assertThat(info.to).isEqualTo(KeyguardState.DREAMING)
+ assertThat(info.animator).isNotNull()
+
+ coroutineContext.cancelChildren()
+ }
+
private fun startingToWake() =
WakefulnessModel(
WakefulnessState.STARTING_TO_WAKE,
@@ -199,4 +566,12 @@
WakeSleepReason.OTHER,
WakeSleepReason.OTHER
)
+
+ private fun startingToSleep() =
+ WakefulnessModel(
+ WakefulnessState.STARTING_TO_SLEEP,
+ true,
+ WakeSleepReason.OTHER,
+ WakeSleepReason.OTHER
+ )
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt
index a6fc13b..7f48ea1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt
@@ -30,11 +30,11 @@
import com.android.systemui.keyguard.data.BouncerView
import com.android.systemui.keyguard.data.BouncerViewDelegate
import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
+import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN
+import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE
import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
import com.android.systemui.keyguard.shared.model.KeyguardBouncerModel
import com.android.systemui.plugins.ActivityStarter
-import com.android.systemui.statusbar.phone.KeyguardBouncer.EXPANSION_HIDDEN
-import com.android.systemui.statusbar.phone.KeyguardBouncer.EXPANSION_VISIBLE
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.mockito.any
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModelTest.kt
new file mode 100644
index 0000000..7fa204b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModelTest.kt
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.animation.Interpolators.EMPHASIZED_ACCELERATE
+import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.domain.interactor.FromGoneTransitionInteractor.Companion.TO_DREAMING_DURATION
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.shared.model.AnimationParams
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionState
+import com.android.systemui.keyguard.shared.model.TransitionStep
+import com.android.systemui.keyguard.ui.viewmodel.GoneToDreamingTransitionViewModel.Companion.LOCKSCREEN_ALPHA
+import com.android.systemui.keyguard.ui.viewmodel.GoneToDreamingTransitionViewModel.Companion.LOCKSCREEN_TRANSLATION_Y
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@SmallTest
+@RunWith(JUnit4::class)
+class GoneToDreamingTransitionViewModelTest : SysuiTestCase() {
+ private lateinit var underTest: GoneToDreamingTransitionViewModel
+ private lateinit var repository: FakeKeyguardTransitionRepository
+
+ @Before
+ fun setUp() {
+ repository = FakeKeyguardTransitionRepository()
+ val interactor = KeyguardTransitionInteractor(repository)
+ underTest = GoneToDreamingTransitionViewModel(interactor)
+ }
+
+ @Test
+ fun lockscreenFadeOut() =
+ runTest(UnconfinedTestDispatcher()) {
+ val values = mutableListOf<Float>()
+
+ val job = underTest.lockscreenAlpha.onEach { values.add(it) }.launchIn(this)
+
+ // Should start running here...
+ repository.sendTransitionStep(step(0f))
+ repository.sendTransitionStep(step(0.1f))
+ repository.sendTransitionStep(step(0.2f))
+ // ...up to here
+ repository.sendTransitionStep(step(0.3f))
+ repository.sendTransitionStep(step(1f))
+
+ // Only three values should be present, since the dream overlay runs for a small
+ // fraction
+ // of the overall animation time
+ assertThat(values.size).isEqualTo(3)
+ assertThat(values[0]).isEqualTo(1f - animValue(0f, LOCKSCREEN_ALPHA))
+ assertThat(values[1]).isEqualTo(1f - animValue(0.1f, LOCKSCREEN_ALPHA))
+ assertThat(values[2]).isEqualTo(1f - animValue(0.2f, LOCKSCREEN_ALPHA))
+
+ job.cancel()
+ }
+
+ @Test
+ fun lockscreenTranslationY() =
+ runTest(UnconfinedTestDispatcher()) {
+ val values = mutableListOf<Float>()
+
+ val pixels = 100
+ val job =
+ underTest.lockscreenTranslationY(pixels).onEach { values.add(it) }.launchIn(this)
+
+ // Should start running here...
+ repository.sendTransitionStep(step(0f))
+ repository.sendTransitionStep(step(0.3f))
+ repository.sendTransitionStep(step(0.5f))
+ // ...up to here
+ repository.sendTransitionStep(step(1f))
+ // And a final reset event on CANCEL
+ repository.sendTransitionStep(step(0.8f, TransitionState.CANCELED))
+
+ assertThat(values.size).isEqualTo(4)
+ assertThat(values[0])
+ .isEqualTo(
+ EMPHASIZED_ACCELERATE.getInterpolation(
+ animValue(0f, LOCKSCREEN_TRANSLATION_Y)
+ ) * pixels
+ )
+ assertThat(values[1])
+ .isEqualTo(
+ EMPHASIZED_ACCELERATE.getInterpolation(
+ animValue(0.3f, LOCKSCREEN_TRANSLATION_Y)
+ ) * pixels
+ )
+ assertThat(values[2])
+ .isEqualTo(
+ EMPHASIZED_ACCELERATE.getInterpolation(
+ animValue(0.5f, LOCKSCREEN_TRANSLATION_Y)
+ ) * pixels
+ )
+ assertThat(values[3]).isEqualTo(0f)
+ job.cancel()
+ }
+
+ private fun animValue(stepValue: Float, params: AnimationParams): Float {
+ val totalDuration = TO_DREAMING_DURATION
+ val startValue = (params.startTime / totalDuration).toFloat()
+
+ val multiplier = (totalDuration / params.duration).toFloat()
+ return (stepValue - startValue) * multiplier
+ }
+
+ private fun step(
+ value: Float,
+ state: TransitionState = TransitionState.RUNNING
+ ): TransitionStep {
+ return TransitionStep(
+ from = KeyguardState.GONE,
+ to = KeyguardState.DREAMING,
+ value = value,
+ transitionState = state,
+ ownerName = "GoneToDreamingTransitionViewModelTest"
+ )
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt
index 7390591..539fc2c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt
@@ -67,8 +67,7 @@
repository.sendTransitionStep(step(1f))
// Only three values should be present, since the dream overlay runs for a small
- // fraction
- // of the overall animation time
+ // fraction of the overall animation time
assertThat(values.size).isEqualTo(3)
assertThat(values[0]).isEqualTo(1f - animValue(0f, LOCKSCREEN_ALPHA))
assertThat(values[1]).isEqualTo(1f - animValue(0.1f, LOCKSCREEN_ALPHA))
@@ -92,8 +91,10 @@
repository.sendTransitionStep(step(0.5f))
// ...up to here
repository.sendTransitionStep(step(1f))
+ // And a final reset event on FINISHED
+ repository.sendTransitionStep(step(1f, TransitionState.FINISHED))
- assertThat(values.size).isEqualTo(3)
+ assertThat(values.size).isEqualTo(4)
assertThat(values[0])
.isEqualTo(
EMPHASIZED_ACCELERATE.getInterpolation(
@@ -112,6 +113,8 @@
animValue(0.5f, LOCKSCREEN_TRANSLATION_Y)
) * pixels
)
+ assertThat(values[3]).isEqualTo(0f)
+
job.cancel()
}
@@ -123,12 +126,15 @@
return (stepValue - startValue) * multiplier
}
- private fun step(value: Float): TransitionStep {
+ private fun step(
+ value: Float,
+ state: TransitionState = TransitionState.RUNNING
+ ): TransitionStep {
return TransitionStep(
from = KeyguardState.LOCKSCREEN,
to = KeyguardState.DREAMING,
value = value,
- transitionState = TransitionState.RUNNING,
+ transitionState = state,
ownerName = "LockscreenToDreamingTransitionViewModelTest"
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferFactoryTest.kt
new file mode 100644
index 0000000..411b1bd
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferFactoryTest.kt
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.log.table
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.time.FakeSystemClock
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+
+@SmallTest
+class TableLogBufferFactoryTest : SysuiTestCase() {
+ private val dumpManager: DumpManager = mock()
+ private val systemClock = FakeSystemClock()
+ private val underTest = TableLogBufferFactory(dumpManager, systemClock)
+
+ @Test
+ fun `create - always creates new instance`() {
+ val b1 = underTest.create(NAME_1, SIZE)
+ val b1_copy = underTest.create(NAME_1, SIZE)
+ val b2 = underTest.create(NAME_2, SIZE)
+ val b2_copy = underTest.create(NAME_2, SIZE)
+
+ assertThat(b1).isNotSameInstanceAs(b1_copy)
+ assertThat(b1).isNotSameInstanceAs(b2)
+ assertThat(b2).isNotSameInstanceAs(b2_copy)
+ }
+
+ @Test
+ fun `getOrCreate - reuses instance`() {
+ val b1 = underTest.getOrCreate(NAME_1, SIZE)
+ val b1_copy = underTest.getOrCreate(NAME_1, SIZE)
+ val b2 = underTest.getOrCreate(NAME_2, SIZE)
+ val b2_copy = underTest.getOrCreate(NAME_2, SIZE)
+
+ assertThat(b1).isSameInstanceAs(b1_copy)
+ assertThat(b2).isSameInstanceAs(b2_copy)
+ assertThat(b1).isNotSameInstanceAs(b2)
+ assertThat(b1_copy).isNotSameInstanceAs(b2_copy)
+ }
+
+ companion object {
+ const val NAME_1 = "name 1"
+ const val NAME_2 = "name 2"
+
+ const val SIZE = 8
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataCombineLatestTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataCombineLatestTest.java
index 4d2d0f0..c0639f3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataCombineLatestTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataCombineLatestTest.java
@@ -79,7 +79,7 @@
USER_ID, true, APP, null, ARTIST, TITLE, null,
new ArrayList<>(), new ArrayList<>(), null, PACKAGE, null, null, null, true, null,
MediaData.PLAYBACK_LOCAL, false, KEY, false, false, false, 0L,
- InstanceId.fakeInstanceId(-1), -1);
+ InstanceId.fakeInstanceId(-1), -1, false);
mDeviceData = new MediaDeviceData(true, null, DEVICE_NAME, null, false);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt
index 52b694f..1687fdc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt
@@ -17,6 +17,7 @@
package com.android.systemui.media.controls.pipeline
import android.app.Notification
+import android.app.Notification.FLAG_NO_CLEAR
import android.app.Notification.MediaStyle
import android.app.PendingIntent
import android.app.smartspace.SmartspaceAction
@@ -228,6 +229,7 @@
whenever(mediaSmartspaceTarget.iconGrid).thenReturn(validRecommendationList)
whenever(mediaSmartspaceTarget.creationTimeMillis).thenReturn(1234L)
whenever(mediaFlags.areMediaSessionActionsEnabled(any(), any())).thenReturn(false)
+ whenever(mediaFlags.isExplicitIndicatorEnabled()).thenReturn(true)
whenever(logger.getNewInstanceId()).thenReturn(instanceIdSequence.newInstanceId())
}
@@ -300,6 +302,60 @@
}
@Test
+ fun testLoadMetadata_withExplicitIndicator() {
+ val metadata =
+ MediaMetadata.Builder().run {
+ putString(MediaMetadata.METADATA_KEY_ARTIST, SESSION_ARTIST)
+ putString(MediaMetadata.METADATA_KEY_TITLE, SESSION_TITLE)
+ putLong(
+ MediaConstants.METADATA_KEY_IS_EXPLICIT,
+ MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT
+ )
+ build()
+ }
+ whenever(mediaControllerFactory.create(anyObject())).thenReturn(controller)
+ whenever(controller.metadata).thenReturn(metadata)
+
+ mediaDataManager.addListener(listener)
+ mediaDataManager.onNotificationAdded(KEY, mediaNotification)
+
+ assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
+ assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
+ verify(listener)
+ .onMediaDataLoaded(
+ eq(KEY),
+ eq(null),
+ capture(mediaDataCaptor),
+ eq(true),
+ eq(0),
+ eq(false)
+ )
+ assertThat(mediaDataCaptor.value!!.isExplicit).isTrue()
+ }
+
+ @Test
+ fun testOnMetaDataLoaded_withoutExplicitIndicator() {
+ whenever(mediaControllerFactory.create(anyObject())).thenReturn(controller)
+ whenever(controller.metadata).thenReturn(metadataBuilder.build())
+
+ mediaDataManager.addListener(listener)
+ mediaDataManager.onNotificationAdded(KEY, mediaNotification)
+
+ assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
+ assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
+ verify(listener)
+ .onMediaDataLoaded(
+ eq(KEY),
+ eq(null),
+ capture(mediaDataCaptor),
+ eq(true),
+ eq(0),
+ eq(false)
+ )
+ assertThat(mediaDataCaptor.value!!.isExplicit).isFalse()
+ }
+
+ @Test
fun testOnMetaDataLoaded_callsListener() {
addNotificationAndLoad()
verify(logger)
@@ -603,6 +659,53 @@
}
@Test
+ fun testAddResumptionControls_withExplicitIndicator() {
+ val bundle = Bundle()
+ // WHEN resumption controls are added with explicit indicator
+ bundle.putLong(
+ MediaConstants.METADATA_KEY_IS_EXPLICIT,
+ MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT
+ )
+ val desc =
+ MediaDescription.Builder().run {
+ setTitle(SESSION_TITLE)
+ setExtras(bundle)
+ build()
+ }
+ val currentTime = clock.elapsedRealtime()
+ mediaDataManager.addResumptionControls(
+ USER_ID,
+ desc,
+ Runnable {},
+ session.sessionToken,
+ APP_NAME,
+ pendingIntent,
+ PACKAGE_NAME
+ )
+ assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
+ assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
+ // THEN the media data indicates that it is for resumption
+ verify(listener)
+ .onMediaDataLoaded(
+ eq(PACKAGE_NAME),
+ eq(null),
+ capture(mediaDataCaptor),
+ eq(true),
+ eq(0),
+ eq(false)
+ )
+ val data = mediaDataCaptor.value
+ assertThat(data.resumption).isTrue()
+ assertThat(data.song).isEqualTo(SESSION_TITLE)
+ assertThat(data.app).isEqualTo(APP_NAME)
+ assertThat(data.actions).hasSize(1)
+ assertThat(data.semanticActions!!.playOrPause).isNotNull()
+ assertThat(data.lastActive).isAtLeast(currentTime)
+ assertThat(data.isExplicit).isTrue()
+ verify(logger).logResumeMediaAdded(anyInt(), eq(PACKAGE_NAME), eq(data.instanceId))
+ }
+
+ @Test
fun testResumptionDisabled_dismissesResumeControls() {
// WHEN there are resume controls and resumption is switched off
val desc =
@@ -1349,6 +1452,39 @@
assertThat(mediaDataCaptor.value.semanticActions).isNull()
}
+ @Test
+ fun testNoClearNotOngoing_canDismiss() {
+ mediaNotification =
+ SbnBuilder().run {
+ setPkg(PACKAGE_NAME)
+ modifyNotification(context).also {
+ it.setSmallIcon(android.R.drawable.ic_media_pause)
+ it.setStyle(MediaStyle().apply { setMediaSession(session.sessionToken) })
+ it.setOngoing(false)
+ it.setFlag(FLAG_NO_CLEAR, true)
+ }
+ build()
+ }
+ addNotificationAndLoad()
+ assertThat(mediaDataCaptor.value.isClearable).isTrue()
+ }
+
+ @Test
+ fun testOngoing_cannotDismiss() {
+ mediaNotification =
+ SbnBuilder().run {
+ setPkg(PACKAGE_NAME)
+ modifyNotification(context).also {
+ it.setSmallIcon(android.R.drawable.ic_media_pause)
+ it.setStyle(MediaStyle().apply { setMediaSession(session.sessionToken) })
+ it.setOngoing(true)
+ }
+ build()
+ }
+ addNotificationAndLoad()
+ assertThat(mediaDataCaptor.value.isClearable).isFalse()
+ }
+
/** Helper function to add a media notification and capture the resulting MediaData */
private fun addNotificationAndLoad() {
mediaDataManager.onNotificationAdded(KEY, mediaNotification)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt
index 039dd4d..e4e95e5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt
@@ -20,6 +20,7 @@
import android.content.res.Configuration
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
+import android.util.MathUtils.abs
import androidx.test.filters.SmallTest
import com.android.internal.logging.InstanceId
import com.android.systemui.SysuiTestCase
@@ -31,14 +32,11 @@
import com.android.systemui.media.controls.models.recommendation.SmartspaceMediaData
import com.android.systemui.media.controls.pipeline.EMPTY_SMARTSPACE_MEDIA_DATA
import com.android.systemui.media.controls.pipeline.MediaDataManager
-import com.android.systemui.media.controls.ui.MediaCarouselController.Companion.ANIMATION_BASE_DURATION
-import com.android.systemui.media.controls.ui.MediaCarouselController.Companion.DURATION
-import com.android.systemui.media.controls.ui.MediaCarouselController.Companion.PAGINATION_DELAY
-import com.android.systemui.media.controls.ui.MediaCarouselController.Companion.TRANSFORM_BEZIER
import com.android.systemui.media.controls.ui.MediaHierarchyManager.Companion.LOCATION_QS
import com.android.systemui.media.controls.util.MediaUiEventLogger
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.qs.PageIndicator
import com.android.systemui.statusbar.notification.collection.provider.OnReorderingAllowedListener
import com.android.systemui.statusbar.notification.collection.provider.VisualStabilityProvider
import com.android.systemui.statusbar.policy.ConfigurationController
@@ -56,6 +54,7 @@
import org.mockito.ArgumentCaptor
import org.mockito.Captor
import org.mockito.Mock
+import org.mockito.Mockito.floatThat
import org.mockito.Mockito.mock
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when` as whenever
@@ -86,6 +85,8 @@
@Mock lateinit var debugLogger: MediaCarouselControllerLogger
@Mock lateinit var mediaViewController: MediaViewController
@Mock lateinit var smartspaceMediaData: SmartspaceMediaData
+ @Mock lateinit var mediaCarousel: MediaScrollView
+ @Mock lateinit var pageIndicator: PageIndicator
@Captor lateinit var listener: ArgumentCaptor<MediaDataManager.Listener>
@Captor
lateinit var configListener: ArgumentCaptor<ConfigurationController.ConfigurationListener>
@@ -647,25 +648,22 @@
@Test
fun testSetCurrentState_UpdatePageIndicatorAlphaWhenSquish() {
val delta = 0.0001F
- val paginationSquishMiddle =
- TRANSFORM_BEZIER.getInterpolation(
- (PAGINATION_DELAY + DURATION / 2) / ANIMATION_BASE_DURATION
- )
- val paginationSquishEnd =
- TRANSFORM_BEZIER.getInterpolation(
- (PAGINATION_DELAY + DURATION) / ANIMATION_BASE_DURATION
- )
+ mediaCarouselController.mediaCarousel = mediaCarousel
+ mediaCarouselController.pageIndicator = pageIndicator
+ whenever(mediaCarousel.measuredHeight).thenReturn(100)
+ whenever(pageIndicator.translationY).thenReturn(80F)
+ whenever(pageIndicator.height).thenReturn(10)
whenever(mediaHostStatesManager.mediaHostStates)
.thenReturn(mutableMapOf(LOCATION_QS to mediaHostState))
whenever(mediaHostState.visible).thenReturn(true)
mediaCarouselController.currentEndLocation = LOCATION_QS
- whenever(mediaHostState.squishFraction).thenReturn(paginationSquishMiddle)
+ whenever(mediaHostState.squishFraction).thenReturn(0.938F)
mediaCarouselController.updatePageIndicatorAlpha()
- assertEquals(mediaCarouselController.pageIndicator.alpha, 0.5F, delta)
+ verify(pageIndicator).alpha = floatThat { abs(it - 0.5F) < delta }
- whenever(mediaHostState.squishFraction).thenReturn(paginationSquishEnd)
+ whenever(mediaHostState.squishFraction).thenReturn(1.0F)
mediaCarouselController.updatePageIndicatorAlpha()
- assertEquals(mediaCarouselController.pageIndicator.alpha, 1.0F, delta)
+ verify(pageIndicator).alpha = floatThat { abs(it - 1.0F) < delta }
}
@Ignore("b/253229241")
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaControlPanelTest.kt
index b65f5cb..b35dd26 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaControlPanelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaControlPanelTest.kt
@@ -54,6 +54,7 @@
import androidx.lifecycle.LiveData
import androidx.test.filters.SmallTest
import com.android.internal.logging.InstanceId
+import com.android.internal.widget.CachingIconView
import com.android.systemui.ActivityIntentHelper
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
@@ -81,6 +82,7 @@
import com.android.systemui.statusbar.NotificationLockscreenUserManager
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.surfaceeffects.ripple.MultiRippleView
+import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseAnimationConfig
import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseView
import com.android.systemui.util.animation.TransitionLayout
import com.android.systemui.util.concurrency.FakeExecutor
@@ -154,6 +156,7 @@
@Mock private lateinit var albumView: ImageView
private lateinit var titleText: TextView
private lateinit var artistText: TextView
+ private lateinit var explicitIndicator: CachingIconView
private lateinit var seamless: ViewGroup
private lateinit var seamlessButton: View
@Mock private lateinit var seamlessBackground: RippleDrawable
@@ -216,14 +219,15 @@
this.set(Flags.UMO_SURFACE_RIPPLE, false)
this.set(Flags.UMO_TURBULENCE_NOISE, false)
this.set(Flags.MEDIA_FALSING_PENALTY, true)
+ this.set(Flags.MEDIA_EXPLICIT_INDICATOR, true)
}
@JvmField @Rule val mockito = MockitoJUnit.rule()
@Before
fun setUp() {
- bgExecutor = FakeExecutor(FakeSystemClock())
- mainExecutor = FakeExecutor(FakeSystemClock())
+ bgExecutor = FakeExecutor(clock)
+ mainExecutor = FakeExecutor(clock)
whenever(mediaViewController.expandedLayout).thenReturn(expandedSet)
whenever(mediaViewController.collapsedLayout).thenReturn(collapsedSet)
@@ -350,6 +354,7 @@
appIcon = ImageView(context)
titleText = TextView(context)
artistText = TextView(context)
+ explicitIndicator = CachingIconView(context).also { it.id = R.id.media_explicit_indicator }
seamless = FrameLayout(context)
seamless.foreground = seamlessBackground
seamlessButton = View(context)
@@ -396,6 +401,7 @@
whenever(albumView.foreground).thenReturn(mock(Drawable::class.java))
whenever(viewHolder.titleText).thenReturn(titleText)
whenever(viewHolder.artistText).thenReturn(artistText)
+ whenever(viewHolder.explicitIndicator).thenReturn(explicitIndicator)
whenever(seamlessBackground.getDrawable(0)).thenReturn(mock(GradientDrawable::class.java))
whenever(viewHolder.seamless).thenReturn(seamless)
whenever(viewHolder.seamlessButton).thenReturn(seamlessButton)
@@ -1019,6 +1025,7 @@
@Test
fun bindText() {
+ useRealConstraintSets()
player.attachPlayer(viewHolder)
player.bindPlayer(mediaData, PACKAGE)
@@ -1036,6 +1043,8 @@
handler.onAnimationEnd(mockAnimator)
assertThat(titleText.getText()).isEqualTo(TITLE)
assertThat(artistText.getText()).isEqualTo(ARTIST)
+ assertThat(expandedSet.getVisibility(explicitIndicator.id)).isEqualTo(ConstraintSet.GONE)
+ assertThat(collapsedSet.getVisibility(explicitIndicator.id)).isEqualTo(ConstraintSet.GONE)
// Rebinding should not trigger animation
player.bindPlayer(mediaData, PACKAGE)
@@ -1043,6 +1052,36 @@
}
@Test
+ fun bindTextWithExplicitIndicator() {
+ useRealConstraintSets()
+ val mediaDataWitExp = mediaData.copy(isExplicit = true)
+ player.attachPlayer(viewHolder)
+ player.bindPlayer(mediaDataWitExp, PACKAGE)
+
+ // Capture animation handler
+ val captor = argumentCaptor<Animator.AnimatorListener>()
+ verify(mockAnimator, times(2)).addListener(captor.capture())
+ val handler = captor.value
+
+ // Validate text views unchanged but animation started
+ assertThat(titleText.getText()).isEqualTo("")
+ assertThat(artistText.getText()).isEqualTo("")
+ verify(mockAnimator, times(1)).start()
+
+ // Binding only after animator runs
+ handler.onAnimationEnd(mockAnimator)
+ assertThat(titleText.getText()).isEqualTo(TITLE)
+ assertThat(artistText.getText()).isEqualTo(ARTIST)
+ assertThat(expandedSet.getVisibility(explicitIndicator.id)).isEqualTo(ConstraintSet.VISIBLE)
+ assertThat(collapsedSet.getVisibility(explicitIndicator.id))
+ .isEqualTo(ConstraintSet.VISIBLE)
+
+ // Rebinding should not trigger animation
+ player.bindPlayer(mediaData, PACKAGE)
+ verify(mockAnimator, times(3)).start()
+ }
+
+ @Test
fun bindTextInterrupted() {
val data0 = mediaData.copy(artist = "ARTIST_0")
val data1 = mediaData.copy(artist = "ARTIST_1")
@@ -2083,6 +2122,27 @@
assertThat(player.mRipplesFinishedListener).isNull()
}
+ @Test
+ fun playTurbulenceNoise_finishesAfterDuration() {
+ fakeFeatureFlag.set(Flags.UMO_SURFACE_RIPPLE, true)
+ fakeFeatureFlag.set(Flags.UMO_TURBULENCE_NOISE, true)
+
+ player.attachPlayer(viewHolder)
+
+ mainExecutor.execute {
+ player.mRipplesFinishedListener.onRipplesFinish()
+
+ assertThat(turbulenceNoiseView.visibility).isEqualTo(View.VISIBLE)
+
+ clock.advanceTime(
+ MediaControlPanel.TURBULENCE_NOISE_PLAY_DURATION +
+ TurbulenceNoiseAnimationConfig.DEFAULT_EASING_DURATION_IN_MILLIS.toLong()
+ )
+
+ assertThat(turbulenceNoiseView.visibility).isEqualTo(View.INVISIBLE)
+ }
+ }
+
private fun getScrubbingChangeListener(): SeekBarViewModel.ScrubbingChangeListener =
withArgCaptor {
verify(seekBarViewModel).setScrubbingChangeListener(capture())
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaViewControllerTest.kt
index 35b0eb6..4ed6d7c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaViewControllerTest.kt
@@ -22,13 +22,6 @@
import androidx.test.filters.SmallTest
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
-import com.android.systemui.media.controls.ui.MediaCarouselController.Companion.ANIMATION_BASE_DURATION
-import com.android.systemui.media.controls.ui.MediaCarouselController.Companion.CONTROLS_DELAY
-import com.android.systemui.media.controls.ui.MediaCarouselController.Companion.DETAILS_DELAY
-import com.android.systemui.media.controls.ui.MediaCarouselController.Companion.DURATION
-import com.android.systemui.media.controls.ui.MediaCarouselController.Companion.MEDIACONTAINERS_DELAY
-import com.android.systemui.media.controls.ui.MediaCarouselController.Companion.MEDIATITLES_DELAY
-import com.android.systemui.media.controls.ui.MediaCarouselController.Companion.TRANSFORM_BEZIER
import com.android.systemui.util.animation.MeasurementInput
import com.android.systemui.util.animation.TransitionLayout
import com.android.systemui.util.animation.TransitionViewState
@@ -60,9 +53,10 @@
@Mock private lateinit var controlWidgetState: WidgetState
@Mock private lateinit var bgWidgetState: WidgetState
@Mock private lateinit var mediaTitleWidgetState: WidgetState
+ @Mock private lateinit var mediaSubTitleWidgetState: WidgetState
@Mock private lateinit var mediaContainerWidgetState: WidgetState
- val delta = 0.0001F
+ val delta = 0.1F
private lateinit var mediaViewController: MediaViewController
@@ -76,10 +70,11 @@
@Test
fun testObtainViewState_applySquishFraction_toPlayerTransitionViewState_height() {
mediaViewController.attach(player, MediaViewController.TYPE.PLAYER)
- player.measureState = TransitionViewState().apply {
- this.height = 100
- this.measureHeight = 100
- }
+ player.measureState =
+ TransitionViewState().apply {
+ this.height = 100
+ this.measureHeight = 100
+ }
mediaHostStateHolder.expansion = 1f
val widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY)
val heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY)
@@ -128,29 +123,21 @@
R.id.header_artist to detailWidgetState
)
)
-
- val detailSquishMiddle =
- TRANSFORM_BEZIER.getInterpolation(
- (DETAILS_DELAY + DURATION / 2) / ANIMATION_BASE_DURATION
- )
- mediaViewController.squishViewState(mockViewState, detailSquishMiddle)
+ whenever(mockCopiedState.measureHeight).thenReturn(200)
+ // detail widgets occupy [90, 100]
+ whenever(detailWidgetState.y).thenReturn(90F)
+ whenever(detailWidgetState.height).thenReturn(10)
+ // control widgets occupy [150, 170]
+ whenever(controlWidgetState.y).thenReturn(150F)
+ whenever(controlWidgetState.height).thenReturn(20)
+ // in current beizer, when the progress reach 0.38, the result will be 0.5
+ mediaViewController.squishViewState(mockViewState, 119F / 200F)
verify(detailWidgetState).alpha = floatThat { kotlin.math.abs(it - 0.5F) < delta }
-
- val detailSquishEnd =
- TRANSFORM_BEZIER.getInterpolation((DETAILS_DELAY + DURATION) / ANIMATION_BASE_DURATION)
- mediaViewController.squishViewState(mockViewState, detailSquishEnd)
+ mediaViewController.squishViewState(mockViewState, 150F / 200F)
verify(detailWidgetState).alpha = floatThat { kotlin.math.abs(it - 1.0F) < delta }
-
- val controlSquishMiddle =
- TRANSFORM_BEZIER.getInterpolation(
- (CONTROLS_DELAY + DURATION / 2) / ANIMATION_BASE_DURATION
- )
- mediaViewController.squishViewState(mockViewState, controlSquishMiddle)
+ mediaViewController.squishViewState(mockViewState, 181.4F / 200F)
verify(controlWidgetState).alpha = floatThat { kotlin.math.abs(it - 0.5F) < delta }
-
- val controlSquishEnd =
- TRANSFORM_BEZIER.getInterpolation((CONTROLS_DELAY + DURATION) / ANIMATION_BASE_DURATION)
- mediaViewController.squishViewState(mockViewState, controlSquishEnd)
+ mediaViewController.squishViewState(mockViewState, 200F / 200F)
verify(controlWidgetState).alpha = floatThat { kotlin.math.abs(it - 1.0F) < delta }
}
@@ -161,36 +148,33 @@
.thenReturn(
mutableMapOf(
R.id.media_title1 to mediaTitleWidgetState,
+ R.id.media_subtitle1 to mediaSubTitleWidgetState,
R.id.media_cover1_container to mediaContainerWidgetState
)
)
+ whenever(mockCopiedState.measureHeight).thenReturn(360)
+ // media container widgets occupy [20, 300]
+ whenever(mediaContainerWidgetState.y).thenReturn(20F)
+ whenever(mediaContainerWidgetState.height).thenReturn(280)
+ // media title widgets occupy [320, 330]
+ whenever(mediaTitleWidgetState.y).thenReturn(320F)
+ whenever(mediaTitleWidgetState.height).thenReturn(10)
+ // media subtitle widgets occupy [340, 350]
+ whenever(mediaSubTitleWidgetState.y).thenReturn(340F)
+ whenever(mediaSubTitleWidgetState.height).thenReturn(10)
- val containerSquishMiddle =
- TRANSFORM_BEZIER.getInterpolation(
- (MEDIACONTAINERS_DELAY + DURATION / 2) / ANIMATION_BASE_DURATION
- )
- mediaViewController.squishViewState(mockViewState, containerSquishMiddle)
+ // in current beizer, when the progress reach 0.38, the result will be 0.5
+ mediaViewController.squishViewState(mockViewState, 307.6F / 360F)
verify(mediaContainerWidgetState).alpha = floatThat { kotlin.math.abs(it - 0.5F) < delta }
-
- val containerSquishEnd =
- TRANSFORM_BEZIER.getInterpolation(
- (MEDIACONTAINERS_DELAY + DURATION) / ANIMATION_BASE_DURATION
- )
- mediaViewController.squishViewState(mockViewState, containerSquishEnd)
+ mediaViewController.squishViewState(mockViewState, 320F / 360F)
verify(mediaContainerWidgetState).alpha = floatThat { kotlin.math.abs(it - 1.0F) < delta }
-
- val titleSquishMiddle =
- TRANSFORM_BEZIER.getInterpolation(
- (MEDIATITLES_DELAY + DURATION / 2) / ANIMATION_BASE_DURATION
- )
- mediaViewController.squishViewState(mockViewState, titleSquishMiddle)
+ // media title and media subtitle are in same widget group, should be calculate together and
+ // have same alpha
+ mediaViewController.squishViewState(mockViewState, 353.8F / 360F)
verify(mediaTitleWidgetState).alpha = floatThat { kotlin.math.abs(it - 0.5F) < delta }
-
- val titleSquishEnd =
- TRANSFORM_BEZIER.getInterpolation(
- (MEDIATITLES_DELAY + DURATION) / ANIMATION_BASE_DURATION
- )
- mediaViewController.squishViewState(mockViewState, titleSquishEnd)
+ verify(mediaSubTitleWidgetState).alpha = floatThat { kotlin.math.abs(it - 0.5F) < delta }
+ mediaViewController.squishViewState(mockViewState, 360F / 360F)
verify(mediaTitleWidgetState).alpha = floatThat { kotlin.math.abs(it - 1.0F) < delta }
+ verify(mediaSubTitleWidgetState).alpha = floatThat { kotlin.math.abs(it - 1.0F) < delta }
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogReceiverTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogReceiverTest.java
index 771b986..3d5dba3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogReceiverTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogReceiverTest.java
@@ -54,36 +54,6 @@
}
@Test
- public void showOutputSwitcher_ExtraPackageName_DialogFactoryCalled() {
- Intent intent = new Intent(Intent.ACTION_SHOW_OUTPUT_SWITCHER);
- intent.putExtra(Intent.EXTRA_PACKAGE_NAME, getContext().getPackageName());
- mMediaOutputDialogReceiver.onReceive(getContext(), intent);
-
- verify(mMockMediaOutputDialogFactory, times(1))
- .create(getContext().getPackageName(), false, null);
- verify(mMockMediaOutputBroadcastDialogFactory, never()).create(any(), anyBoolean(), any());
- }
-
- @Test
- public void showOutputSwitcher_WrongExtraKey_DialogFactoryNotCalled() {
- Intent intent = new Intent(Intent.ACTION_SHOW_OUTPUT_SWITCHER);
- intent.putExtra("Wrong Package Name Key", getContext().getPackageName());
- mMediaOutputDialogReceiver.onReceive(getContext(), intent);
-
- verify(mMockMediaOutputDialogFactory, never()).create(any(), anyBoolean(), any());
- verify(mMockMediaOutputBroadcastDialogFactory, never()).create(any(), anyBoolean(), any());
- }
-
- @Test
- public void showOutputSwitcher_NoExtra_DialogFactoryNotCalled() {
- Intent intent = new Intent(Intent.ACTION_SHOW_OUTPUT_SWITCHER);
- mMediaOutputDialogReceiver.onReceive(getContext(), intent);
-
- verify(mMockMediaOutputDialogFactory, never()).create(any(), anyBoolean(), any());
- verify(mMockMediaOutputBroadcastDialogFactory, never()).create(any(), anyBoolean(), any());
- }
-
- @Test
public void launchMediaOutputDialog_ExtraPackageName_DialogFactoryCalled() {
Intent intent = new Intent(MediaOutputConstants.ACTION_LAUNCH_MEDIA_OUTPUT_DIALOG);
intent.putExtra(MediaOutputConstants.EXTRA_PACKAGE_NAME, getContext().getPackageName());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorControllerTest.kt
index 19d2d33..1042ea7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorControllerTest.kt
@@ -1,12 +1,16 @@
package com.android.systemui.mediaprojection.appselector
import android.content.ComponentName
+import android.os.UserHandle
import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
import com.android.systemui.mediaprojection.appselector.data.RecentTask
import com.android.systemui.mediaprojection.appselector.data.RecentTaskListProvider
import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import org.junit.Test
@@ -21,11 +25,17 @@
private val scope = CoroutineScope(Dispatchers.Unconfined)
private val appSelectorComponentName = ComponentName("com.test", "AppSelector")
+ private val hostUserHandle = UserHandle.of(123)
+ private val otherUserHandle = UserHandle.of(456)
+
private val view: MediaProjectionAppSelectorView = mock()
+ private val featureFlags: FeatureFlags = mock()
private val controller = MediaProjectionAppSelectorController(
taskListProvider,
view,
+ featureFlags,
+ hostUserHandle,
scope,
appSelectorComponentName
)
@@ -98,15 +108,72 @@
)
}
+ @Test
+ fun initRecentTasksWithAppSelectorTasks_enterprisePoliciesDisabled_bindsOnlyTasksWithHostProfile() {
+ givenEnterprisePoliciesFeatureFlag(enabled = false)
+
+ val tasks = listOf(
+ createRecentTask(taskId = 1, userId = hostUserHandle.identifier),
+ createRecentTask(taskId = 2, userId = otherUserHandle.identifier),
+ createRecentTask(taskId = 3, userId = hostUserHandle.identifier),
+ createRecentTask(taskId = 4, userId = otherUserHandle.identifier),
+ createRecentTask(taskId = 5, userId = hostUserHandle.identifier),
+ )
+ taskListProvider.tasks = tasks
+
+ controller.init()
+
+ verify(view).bind(
+ listOf(
+ createRecentTask(taskId = 1, userId = hostUserHandle.identifier),
+ createRecentTask(taskId = 3, userId = hostUserHandle.identifier),
+ createRecentTask(taskId = 5, userId = hostUserHandle.identifier),
+ )
+ )
+ }
+
+ @Test
+ fun initRecentTasksWithAppSelectorTasks_enterprisePoliciesEnabled_bindsAllTasks() {
+ givenEnterprisePoliciesFeatureFlag(enabled = true)
+
+ val tasks = listOf(
+ createRecentTask(taskId = 1, userId = hostUserHandle.identifier),
+ createRecentTask(taskId = 2, userId = otherUserHandle.identifier),
+ createRecentTask(taskId = 3, userId = hostUserHandle.identifier),
+ createRecentTask(taskId = 4, userId = otherUserHandle.identifier),
+ createRecentTask(taskId = 5, userId = hostUserHandle.identifier),
+ )
+ taskListProvider.tasks = tasks
+
+ controller.init()
+
+ // TODO(b/233348916) should filter depending on the policies
+ verify(view).bind(
+ listOf(
+ createRecentTask(taskId = 1, userId = hostUserHandle.identifier),
+ createRecentTask(taskId = 2, userId = otherUserHandle.identifier),
+ createRecentTask(taskId = 3, userId = hostUserHandle.identifier),
+ createRecentTask(taskId = 4, userId = otherUserHandle.identifier),
+ createRecentTask(taskId = 5, userId = hostUserHandle.identifier),
+ )
+ )
+ }
+
+ private fun givenEnterprisePoliciesFeatureFlag(enabled: Boolean) {
+ whenever(featureFlags.isEnabled(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING_ENTERPRISE_POLICIES))
+ .thenReturn(enabled)
+ }
+
private fun createRecentTask(
taskId: Int,
- topActivityComponent: ComponentName? = null
+ topActivityComponent: ComponentName? = null,
+ userId: Int = hostUserHandle.identifier
): RecentTask {
return RecentTask(
taskId = taskId,
topActivityComponent = topActivityComponent,
baseIntentComponent = ComponentName("com", "Test"),
- userId = 0,
+ userId = userId,
colorBackground = 0
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
index 9bf27a2..8b0342e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
@@ -51,6 +51,7 @@
import com.android.systemui.model.SysUiState;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.shared.recents.utilities.Utilities;
+import com.android.systemui.shared.system.TaskStackChangeListeners;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.AutoHideController;
import com.android.systemui.statusbar.phone.LightBarController;
@@ -102,10 +103,10 @@
mock(NavBarHelper.class),
mTaskbarDelegate,
mNavigationBarFactory,
- mock(StatusBarKeyguardViewManager.class),
mock(DumpManager.class),
mock(AutoHideController.class),
mock(LightBarController.class),
+ TaskStackChangeListeners.getTestInstance(),
Optional.of(mock(Pip.class)),
Optional.of(mock(BackAnimation.class)),
mock(FeatureFlags.class)));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
index 80adbf0..2ad865e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
@@ -28,6 +28,7 @@
import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.HOME_BUTTON_LONG_PRESS_DURATION_MS;
import static com.android.systemui.navigationbar.NavigationBar.NavBarActionEvent.NAVBAR_ASSIST_LONGPRESS;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -44,6 +45,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.ActivityManager;
import android.content.Context;
import android.content.res.Resources;
import android.hardware.display.DisplayManagerGlobal;
@@ -90,6 +92,7 @@
import com.android.systemui.shade.NotificationShadeWindowView;
import com.android.systemui.shade.ShadeController;
import com.android.systemui.shared.rotation.RotationButtonController;
+import com.android.systemui.shared.system.TaskStackChangeListeners;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationShadeDepthController;
@@ -203,6 +206,8 @@
private ViewRootImpl mViewRootImpl;
private FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
private DeviceConfigProxyFake mDeviceConfigProxyFake = new DeviceConfigProxyFake();
+ private TaskStackChangeListeners mTaskStackChangeListeners =
+ TaskStackChangeListeners.getTestInstance();
@Rule
public final LeakCheckedTest.SysuiLeakCheck mLeakCheck = new LeakCheckedTest.SysuiLeakCheck();
@@ -437,6 +442,14 @@
verify(mNavBarHelper, times(1)).getCurrentSysuiState();
}
+ @Test
+ public void testScreenPinningEnabled_updatesSysuiState() {
+ mNavigationBar.init();
+ mTaskStackChangeListeners.getListenerImpl().onLockTaskModeChanged(
+ ActivityManager.LOCK_TASK_MODE_PINNED);
+ verify(mMockSysUiState).setFlag(eq(SYSUI_STATE_SCREEN_PINNING), eq(true));
+ }
+
private NavigationBar createNavBar(Context context) {
DeviceProvisionedController deviceProvisionedController =
mock(DeviceProvisionedController.class);
@@ -481,7 +494,8 @@
mEdgeBackGestureHandler,
Optional.of(mock(BackAnimation.class)),
mUserContextProvider,
- mWakefulnessLifecycle));
+ mWakefulnessLifecycle,
+ mTaskStackChangeListeners));
}
private void processAllMessages() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt
index 1742c69..537dfb8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt
@@ -1,11 +1,14 @@
package com.android.systemui.navigationbar
+import android.app.ActivityManager
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
import com.android.systemui.model.SysUiState
import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler
import com.android.systemui.recents.OverviewProxyService
+import com.android.systemui.shared.system.QuickStepContract
+import com.android.systemui.shared.system.TaskStackChangeListeners
import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.statusbar.phone.AutoHideController
import com.android.systemui.statusbar.phone.LightBarController
@@ -14,6 +17,7 @@
import com.android.wm.shell.pip.Pip
import org.junit.Before
import org.junit.Test
+import org.mockito.ArgumentMatchers
import org.mockito.Mock
import org.mockito.Mockito.`when`
import org.mockito.Mockito.any
@@ -30,6 +34,7 @@
val MODE_GESTURE = 0;
val MODE_THREE_BUTTON = 1;
+ private lateinit var mTaskStackChangeListeners: TaskStackChangeListeners
private lateinit var mTaskbarDelegate: TaskbarDelegate
@Mock
lateinit var mEdgeBackGestureHandlerFactory : EdgeBackGestureHandler.Factory
@@ -69,11 +74,12 @@
`when`(mLightBarControllerFactory.create(any())).thenReturn(mLightBarTransitionController)
`when`(mNavBarHelper.currentSysuiState).thenReturn(mCurrentSysUiState)
`when`(mSysUiState.setFlag(anyInt(), anyBoolean())).thenReturn(mSysUiState)
+ mTaskStackChangeListeners = TaskStackChangeListeners.getTestInstance()
mTaskbarDelegate = TaskbarDelegate(context, mEdgeBackGestureHandlerFactory,
mLightBarControllerFactory)
mTaskbarDelegate.setDependencies(mCommandQueue, mOverviewProxyService, mNavBarHelper,
mNavigationModeController, mSysUiState, mDumpManager, mAutoHideController,
- mLightBarController, mOptionalPip, mBackAnimation)
+ mLightBarController, mOptionalPip, mBackAnimation, mTaskStackChangeListeners)
}
@Test
@@ -90,4 +96,15 @@
mTaskbarDelegate.init(DISPLAY_ID)
verify(mEdgeBackGestureHandler, times(1)).onNavigationModeChanged(MODE_GESTURE)
}
+
+ @Test
+ fun screenPinningEnabled_updatesSysuiState() {
+ mTaskbarDelegate.init(DISPLAY_ID)
+ mTaskStackChangeListeners.listenerImpl.onLockTaskModeChanged(
+ ActivityManager.LOCK_TASK_MODE_PINNED)
+ verify(mSysUiState, times(1)).setFlag(
+ ArgumentMatchers.eq(QuickStepContract.SYSUI_STATE_SCREEN_PINNING),
+ ArgumentMatchers.eq(true)
+ )
+ }
}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
index fc90c1a..8440455 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
@@ -24,7 +24,7 @@
import android.test.suitebuilder.annotation.SmallTest
import androidx.test.runner.AndroidJUnit4
import com.android.systemui.SysuiTestCase
-import com.android.systemui.notetask.NoteTaskIntentResolver.Companion.NOTES_ACTION
+import com.android.systemui.notetask.NoteTaskIntentResolver.Companion.ACTION_CREATE_NOTE
import com.android.systemui.notetask.shortcut.CreateNoteTaskShortcutActivity
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.eq
@@ -50,7 +50,7 @@
@RunWith(AndroidJUnit4::class)
internal class NoteTaskControllerTest : SysuiTestCase() {
- private val notesIntent = Intent(NOTES_ACTION)
+ private val notesIntent = Intent(ACTION_CREATE_NOTE)
@Mock lateinit var context: Context
@Mock lateinit var packageManager: PackageManager
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInitializerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInitializerTest.kt
index 538131a..010ac5b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInitializerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInitializerTest.kt
@@ -106,7 +106,9 @@
// region handleSystemKey
@Test
fun handleSystemKey_receiveValidSystemKey_shouldShowNoteTask() {
- createNoteTaskInitializer().callbacks.handleSystemKey(KeyEvent.KEYCODE_VIDEO_APP_1)
+ createNoteTaskInitializer()
+ .callbacks
+ .handleSystemKey(NoteTaskController.NOTE_TASK_KEY_EVENT)
verify(noteTaskController).showNoteTask()
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskIntentResolverTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskIntentResolverTest.kt
index dd2cc2f..bbe60f4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskIntentResolverTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskIntentResolverTest.kt
@@ -23,11 +23,10 @@
import android.content.pm.PackageManager
import android.content.pm.PackageManager.ResolveInfoFlags
import android.content.pm.ResolveInfo
-import android.content.pm.ServiceInfo
import android.test.suitebuilder.annotation.SmallTest
import androidx.test.runner.AndroidJUnit4
import com.android.systemui.SysuiTestCase
-import com.android.systemui.notetask.NoteTaskIntentResolver.Companion.NOTES_ACTION
+import com.android.systemui.notetask.NoteTaskIntentResolver.Companion.ACTION_CREATE_NOTE
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import org.junit.Before
@@ -58,19 +57,13 @@
}
private fun createResolveInfo(
- packageName: String = "PackageName",
- activityInfo: ActivityInfo? = null,
+ activityInfo: ActivityInfo? = createActivityInfo(),
): ResolveInfo {
- return ResolveInfo().apply {
- serviceInfo =
- ServiceInfo().apply {
- applicationInfo = ApplicationInfo().apply { this.packageName = packageName }
- }
- this.activityInfo = activityInfo
- }
+ return ResolveInfo().apply { this.activityInfo = activityInfo }
}
private fun createActivityInfo(
+ packageName: String = "PackageName",
name: String? = "ActivityName",
exported: Boolean = true,
enabled: Boolean = true,
@@ -87,6 +80,7 @@
if (turnScreenOn) {
flags = flags or ActivityInfo.FLAG_TURN_SCREEN_ON
}
+ this.applicationInfo = ApplicationInfo().apply { this.packageName = packageName }
}
}
@@ -107,7 +101,8 @@
val actual = resolver.resolveIntent()
val expected =
- Intent(NOTES_ACTION)
+ Intent(ACTION_CREATE_NOTE)
+ .setPackage("PackageName")
.setComponent(ComponentName("PackageName", "ActivityName"))
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
// Compares the string representation of both intents, as they are different instances.
@@ -204,7 +199,9 @@
@Test
fun resolveIntent_packageNameIsBlank_shouldReturnNull() {
- givenQueryIntentActivities { listOf(createResolveInfo(packageName = "")) }
+ givenQueryIntentActivities {
+ listOf(createResolveInfo(createActivityInfo(packageName = "")))
+ }
val actual = resolver.resolveIntent()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSFactoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSFactoryImplTest.kt
index ca3182a..3281fa9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSFactoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSFactoryImplTest.kt
@@ -28,7 +28,6 @@
import com.android.systemui.qs.tiles.BluetoothTile
import com.android.systemui.qs.tiles.CameraToggleTile
import com.android.systemui.qs.tiles.CastTile
-import com.android.systemui.qs.tiles.CellularTile
import com.android.systemui.qs.tiles.ColorCorrectionTile
import com.android.systemui.qs.tiles.ColorInversionTile
import com.android.systemui.qs.tiles.DataSaverTile
@@ -49,7 +48,6 @@
import com.android.systemui.qs.tiles.RotationLockTile
import com.android.systemui.qs.tiles.ScreenRecordTile
import com.android.systemui.qs.tiles.UiModeNightTile
-import com.android.systemui.qs.tiles.WifiTile
import com.android.systemui.qs.tiles.WorkModeTile
import com.android.systemui.util.leak.GarbageMonitor
import com.google.common.truth.Truth.assertThat
@@ -63,10 +61,8 @@
import org.mockito.Mockito.`when` as whenever
private val specMap = mapOf(
- "wifi" to WifiTile::class.java,
"internet" to InternetTile::class.java,
"bt" to BluetoothTile::class.java,
- "cell" to CellularTile::class.java,
"dnd" to DndTile::class.java,
"inversion" to ColorInversionTile::class.java,
"airplane" to AirplaneModeTile::class.java,
@@ -102,10 +98,8 @@
@Mock(answer = Answers.RETURNS_SELF) private lateinit var customTileBuilder: CustomTile.Builder
@Mock private lateinit var customTile: CustomTile
- @Mock private lateinit var wifiTile: WifiTile
@Mock private lateinit var internetTile: InternetTile
@Mock private lateinit var bluetoothTile: BluetoothTile
- @Mock private lateinit var cellularTile: CellularTile
@Mock private lateinit var dndTile: DndTile
@Mock private lateinit var colorInversionTile: ColorInversionTile
@Mock private lateinit var airplaneTile: AirplaneModeTile
@@ -146,10 +140,8 @@
factory = QSFactoryImpl(
{ qsHost },
{ customTileBuilder },
- { wifiTile },
{ internetTile },
{ bluetoothTile },
- { cellularTile },
{ dndTile },
{ colorInversionTile },
{ airplaneTile },
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplReceiveTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplReceiveTest.kt
new file mode 100644
index 0000000..3710281
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplReceiveTest.kt
@@ -0,0 +1,100 @@
+package com.android.systemui.settings
+
+import android.content.Context
+import android.content.Intent
+import android.content.pm.UserInfo
+import android.os.Handler
+import android.os.UserHandle
+import android.os.UserManager
+import androidx.concurrent.futures.DirectExecutor
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.capture
+import com.google.common.truth.Truth.assertThat
+import java.util.concurrent.Executor
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+import org.mockito.ArgumentCaptor
+import org.mockito.ArgumentMatchers
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(Parameterized::class)
+class UserTrackerImplReceiveTest : SysuiTestCase() {
+
+ companion object {
+
+ @JvmStatic
+ @Parameterized.Parameters
+ fun data(): Iterable<String> =
+ listOf(
+ Intent.ACTION_USER_INFO_CHANGED,
+ Intent.ACTION_MANAGED_PROFILE_AVAILABLE,
+ Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE,
+ Intent.ACTION_MANAGED_PROFILE_ADDED,
+ Intent.ACTION_MANAGED_PROFILE_REMOVED,
+ Intent.ACTION_MANAGED_PROFILE_UNLOCKED
+ )
+ }
+
+ private val executor: Executor = DirectExecutor.INSTANCE
+
+ @Mock private lateinit var context: Context
+ @Mock private lateinit var userManager: UserManager
+ @Mock(stubOnly = true) private lateinit var dumpManager: DumpManager
+ @Mock(stubOnly = true) private lateinit var handler: Handler
+
+ @Parameterized.Parameter lateinit var intentAction: String
+ @Mock private lateinit var callback: UserTracker.Callback
+ @Captor private lateinit var captor: ArgumentCaptor<List<UserInfo>>
+
+ private lateinit var tracker: UserTrackerImpl
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+
+ `when`(context.user).thenReturn(UserHandle.SYSTEM)
+ `when`(context.createContextAsUser(ArgumentMatchers.any(), anyInt())).thenReturn(context)
+
+ tracker = UserTrackerImpl(context, userManager, dumpManager, handler)
+ }
+
+ @Test
+ fun `calls callback and updates profiles when an intent received`() {
+ tracker.initialize(0)
+ tracker.addCallback(callback, executor)
+ val profileID = tracker.userId + 10
+
+ `when`(userManager.getProfiles(anyInt())).thenAnswer { invocation ->
+ val id = invocation.getArgument<Int>(0)
+ val info = UserInfo(id, "", UserInfo.FLAG_FULL)
+ val infoProfile =
+ UserInfo(
+ id + 10,
+ "",
+ "",
+ UserInfo.FLAG_MANAGED_PROFILE,
+ UserManager.USER_TYPE_PROFILE_MANAGED
+ )
+ infoProfile.profileGroupId = id
+ listOf(info, infoProfile)
+ }
+
+ tracker.onReceive(context, Intent(intentAction))
+
+ verify(callback, times(0)).onUserChanged(anyInt(), any())
+ verify(callback, times(1)).onProfilesChanged(capture(captor))
+ assertThat(captor.value.map { it.id }).containsExactly(0, profileID)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt
index 52462c7..e65bbb1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt
@@ -124,6 +124,16 @@
verify(context).registerReceiverForAllUsers(
eq(tracker), capture(captor), isNull(), eq(handler))
+ with(captor.value) {
+ assertThat(countActions()).isEqualTo(7)
+ assertThat(hasAction(Intent.ACTION_USER_SWITCHED)).isTrue()
+ assertThat(hasAction(Intent.ACTION_USER_INFO_CHANGED)).isTrue()
+ assertThat(hasAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE)).isTrue()
+ assertThat(hasAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE)).isTrue()
+ assertThat(hasAction(Intent.ACTION_MANAGED_PROFILE_ADDED)).isTrue()
+ assertThat(hasAction(Intent.ACTION_MANAGED_PROFILE_REMOVED)).isTrue()
+ assertThat(hasAction(Intent.ACTION_MANAGED_PROFILE_UNLOCKED)).isTrue()
+ }
}
@Test
@@ -280,37 +290,6 @@
}
@Test
- fun testCallbackCalledOnProfileChanged() {
- tracker.initialize(0)
- val callback = TestCallback()
- tracker.addCallback(callback, executor)
- val profileID = tracker.userId + 10
-
- `when`(userManager.getProfiles(anyInt())).thenAnswer { invocation ->
- val id = invocation.getArgument<Int>(0)
- val info = UserInfo(id, "", UserInfo.FLAG_FULL)
- val infoProfile = UserInfo(
- id + 10,
- "",
- "",
- UserInfo.FLAG_MANAGED_PROFILE,
- UserManager.USER_TYPE_PROFILE_MANAGED
- )
- infoProfile.profileGroupId = id
- listOf(info, infoProfile)
- }
-
- val intent = Intent(Intent.ACTION_MANAGED_PROFILE_AVAILABLE)
- .putExtra(Intent.EXTRA_USER, UserHandle.of(profileID))
-
- tracker.onReceive(context, intent)
-
- assertThat(callback.calledOnUserChanged).isEqualTo(0)
- assertThat(callback.calledOnProfilesChanged).isEqualTo(1)
- assertThat(callback.lastUserProfiles.map { it.id }).containsExactly(0, profileID)
- }
-
- @Test
fun testCallbackCalledOnUserInfoChanged() {
tracker.initialize(0)
val callback = TestCallback()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/CombinedShadeHeaderConstraintsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/CombinedShadeHeaderConstraintsTest.kt
index 88651c1..f802a5e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/CombinedShadeHeaderConstraintsTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/CombinedShadeHeaderConstraintsTest.kt
@@ -17,6 +17,7 @@
package com.android.systemui.shade
import android.testing.AndroidTestingRunner
+import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintSet
import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID
import androidx.constraintlayout.widget.ConstraintSet.START
@@ -92,12 +93,12 @@
assertThat(getConstraint(R.id.clock).layout.horizontalBias).isEqualTo(0f)
assertThat(getConstraint(R.id.date).layout.startToStart).isEqualTo(PARENT_ID)
- assertThat(getConstraint(R.id.date).layout.horizontalBias).isEqualTo(0f)
+ assertThat(getConstraint(R.id.date).layout.horizontalBias).isEqualTo(0.5f)
assertThat(getConstraint(R.id.batteryRemainingIcon).layout.endToEnd)
.isEqualTo(PARENT_ID)
assertThat(getConstraint(R.id.batteryRemainingIcon).layout.horizontalBias)
- .isEqualTo(1f)
+ .isEqualTo(0.5f)
assertThat(getConstraint(R.id.privacy_container).layout.endToEnd)
.isEqualTo(R.id.end_guide)
@@ -331,10 +332,8 @@
val views = mapOf(
R.id.clock to "clock",
R.id.date to "date",
- R.id.statusIcons to "icons",
R.id.privacy_container to "privacy",
R.id.carrier_group to "carriers",
- R.id.batteryRemainingIcon to "battery",
)
views.forEach { (id, name) ->
assertWithMessage("$name has 0 height in qqs")
@@ -352,11 +351,8 @@
fun testCheckViewsDontChangeSizeBetweenAnimationConstraints() {
val views = mapOf(
R.id.clock to "clock",
- R.id.date to "date",
- R.id.statusIcons to "icons",
R.id.privacy_container to "privacy",
R.id.carrier_group to "carriers",
- R.id.batteryRemainingIcon to "battery",
)
views.forEach { (id, name) ->
expect.withMessage("$name changes height")
@@ -369,8 +365,8 @@
}
private fun Int.fromConstraint() = when (this) {
- -1 -> "MATCH_PARENT"
- -2 -> "WRAP_CONTENT"
+ ViewGroup.LayoutParams.MATCH_PARENT -> "MATCH_PARENT"
+ ViewGroup.LayoutParams.WRAP_CONTENT -> "WRAP_CONTENT"
else -> toString()
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
index a1e9a27..6dd2d61 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
@@ -107,6 +107,7 @@
import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
+import com.android.systemui.keyguard.ui.viewmodel.GoneToDreamingTransitionViewModel;
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBottomAreaViewModel;
import com.android.systemui.keyguard.ui.viewmodel.LockscreenToDreamingTransitionViewModel;
import com.android.systemui.keyguard.ui.viewmodel.LockscreenToOccludedTransitionViewModel;
@@ -299,6 +300,7 @@
@Mock private OccludedToLockscreenTransitionViewModel mOccludedToLockscreenTransitionViewModel;
@Mock private LockscreenToDreamingTransitionViewModel mLockscreenToDreamingTransitionViewModel;
@Mock private LockscreenToOccludedTransitionViewModel mLockscreenToOccludedTransitionViewModel;
+ @Mock private GoneToDreamingTransitionViewModel mGoneToDreamingTransitionViewModel;
@Mock private KeyguardTransitionInteractor mKeyguardTransitionInteractor;
@Mock private CoroutineDispatcher mMainDispatcher;
@@ -522,6 +524,7 @@
mDreamingToLockscreenTransitionViewModel,
mOccludedToLockscreenTransitionViewModel,
mLockscreenToDreamingTransitionViewModel,
+ mGoneToDreamingTransitionViewModel,
mLockscreenToOccludedTransitionViewModel,
mMainDispatcher,
mKeyguardTransitionInteractor,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
index 08a9c96..526dc8d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
@@ -46,11 +46,14 @@
import androidx.test.filters.SmallTest;
import com.android.internal.colorextraction.ColorExtractor;
+import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.keyguard.KeyguardViewMediator;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
@@ -68,6 +71,8 @@
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
+import java.util.List;
+
@RunWith(AndroidTestingRunner.class)
@RunWithLooper
@SmallTest
@@ -91,13 +96,21 @@
@Mock private ShadeExpansionStateManager mShadeExpansionStateManager;
@Mock private ShadeWindowLogger mShadeWindowLogger;
@Captor private ArgumentCaptor<WindowManager.LayoutParams> mLayoutParameters;
+ @Captor private ArgumentCaptor<StatusBarStateController.StateListener> mStateListener;
private NotificationShadeWindowControllerImpl mNotificationShadeWindowController;
-
+ private float mPreferredRefreshRate = -1;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
+ // Preferred refresh rate is equal to the first displayMode's refresh rate
+ mPreferredRefreshRate = mContext.getDisplay().getSupportedModes()[0].getRefreshRate();
+ overrideResource(
+ R.integer.config_keyguardRefreshRate,
+ (int) mPreferredRefreshRate
+ );
+
when(mDozeParameters.getAlwaysOn()).thenReturn(true);
when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors);
@@ -117,6 +130,7 @@
mNotificationShadeWindowController.attach();
verify(mWindowManager).addView(eq(mNotificationShadeWindowView), any());
+ verify(mStatusBarStateController).addCallback(mStateListener.capture(), anyInt());
}
@Test
@@ -334,4 +348,59 @@
assertThat(mLayoutParameters.getValue().screenOrientation)
.isEqualTo(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
}
+
+ @Test
+ public void udfpsEnrolled_minAndMaxRefreshRateSetToPreferredRefreshRate() {
+ // GIVEN udfps is enrolled
+ when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(true);
+
+ // WHEN keyguard is showing
+ setKeyguardShowing();
+
+ // THEN min and max refresh rate is set to the preferredRefreshRate
+ verify(mWindowManager, atLeastOnce()).updateViewLayout(any(), mLayoutParameters.capture());
+ final List<WindowManager.LayoutParams> lpList = mLayoutParameters.getAllValues();
+ final WindowManager.LayoutParams lp = lpList.get(lpList.size() - 1);
+ assertThat(lp.preferredMaxDisplayRefreshRate).isEqualTo(mPreferredRefreshRate);
+ assertThat(lp.preferredMinDisplayRefreshRate).isEqualTo(mPreferredRefreshRate);
+ }
+
+ @Test
+ public void udfpsNotEnrolled_refreshRateUnset() {
+ // GIVEN udfps is NOT enrolled
+ when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(false);
+
+ // WHEN keyguard is showing
+ setKeyguardShowing();
+
+ // THEN min and max refresh rate aren't set (set to 0)
+ verify(mWindowManager, atLeastOnce()).updateViewLayout(any(), mLayoutParameters.capture());
+ final List<WindowManager.LayoutParams> lpList = mLayoutParameters.getAllValues();
+ final WindowManager.LayoutParams lp = lpList.get(lpList.size() - 1);
+ assertThat(lp.preferredMaxDisplayRefreshRate).isEqualTo(0);
+ assertThat(lp.preferredMinDisplayRefreshRate).isEqualTo(0);
+ }
+
+ @Test
+ public void keyguardNotShowing_refreshRateUnset() {
+ // GIVEN UDFPS is enrolled
+ when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(true);
+
+ // WHEN keyguard is NOT showing
+ mNotificationShadeWindowController.setKeyguardShowing(false);
+
+ // THEN min and max refresh rate aren't set (set to 0)
+ verify(mWindowManager, atLeastOnce()).updateViewLayout(any(), mLayoutParameters.capture());
+ final List<WindowManager.LayoutParams> lpList = mLayoutParameters.getAllValues();
+ final WindowManager.LayoutParams lp = lpList.get(lpList.size() - 1);
+ assertThat(lp.preferredMaxDisplayRefreshRate).isEqualTo(0);
+ assertThat(lp.preferredMinDisplayRefreshRate).isEqualTo(0);
+ }
+
+ private void setKeyguardShowing() {
+ mNotificationShadeWindowController.setKeyguardShowing(true);
+ mNotificationShadeWindowController.setKeyguardGoingAway(false);
+ mNotificationShadeWindowController.setKeyguardFadingAway(false);
+ mStateListener.getValue().onStateChanged(StatusBarState.KEYGUARD);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
index 0000c32..fc7cd89 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
@@ -209,9 +209,9 @@
@Test
public void testShowRecentApps() {
- mCommandQueue.showRecentApps(true);
+ mCommandQueue.showRecentApps(true, false);
waitForIdleSync();
- verify(mCallbacks).showRecentApps(eq(true));
+ verify(mCallbacks).showRecentApps(eq(true), eq(false));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
index 4ccbc6d..091bb54 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
@@ -24,6 +24,7 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNotNull;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.doReturn;
@@ -74,6 +75,7 @@
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
+import org.mockito.stubbing.Answer;
import java.util.Collections;
import java.util.List;
@@ -115,8 +117,10 @@
@Spy private PackageManager mPackageManager;
private final boolean mIsReduceBrightColorsAvailable = true;
- private AutoTileManager mAutoTileManager;
+ private AutoTileManager mAutoTileManager; // under test
+
private SecureSettings mSecureSettings;
+ private ManagedProfileController.Callback mManagedProfileCallback;
@Before
public void setUp() throws Exception {
@@ -303,7 +307,7 @@
InOrder inOrderManagedProfile = inOrder(mManagedProfileController);
inOrderManagedProfile.verify(mManagedProfileController).removeCallback(any());
- inOrderManagedProfile.verify(mManagedProfileController, never()).addCallback(any());
+ inOrderManagedProfile.verify(mManagedProfileController).addCallback(any());
if (ColorDisplayManager.isNightDisplayAvailable(mContext)) {
InOrder inOrderNightDisplay = inOrder(mNightDisplayListener);
@@ -504,6 +508,40 @@
}
@Test
+ public void managedProfileAdded_tileAdded() {
+ when(mAutoAddTracker.isAdded(eq("work"))).thenReturn(false);
+ mAutoTileManager = createAutoTileManager(mContext);
+ Mockito.doAnswer((Answer<Object>) invocation -> {
+ mManagedProfileCallback = invocation.getArgument(0);
+ return null;
+ }).when(mManagedProfileController).addCallback(any());
+ mAutoTileManager.init();
+ when(mManagedProfileController.hasActiveProfile()).thenReturn(true);
+
+ mManagedProfileCallback.onManagedProfileChanged();
+
+ verify(mQsTileHost, times(1)).addTile(eq("work"));
+ verify(mAutoAddTracker, times(1)).setTileAdded(eq("work"));
+ }
+
+ @Test
+ public void managedProfileRemoved_tileRemoved() {
+ when(mAutoAddTracker.isAdded(eq("work"))).thenReturn(true);
+ mAutoTileManager = createAutoTileManager(mContext);
+ Mockito.doAnswer((Answer<Object>) invocation -> {
+ mManagedProfileCallback = invocation.getArgument(0);
+ return null;
+ }).when(mManagedProfileController).addCallback(any());
+ mAutoTileManager.init();
+ when(mManagedProfileController.hasActiveProfile()).thenReturn(false);
+
+ mManagedProfileCallback.onManagedProfileChanged();
+
+ verify(mQsTileHost, times(1)).removeTile(eq("work"));
+ verify(mAutoAddTracker, times(1)).setTileRemoved(eq("work"));
+ }
+
+ @Test
public void testEmptyArray_doesNotCrash() {
mContext.getOrCreateTestableResources().addOverride(
R.array.config_quickSettingsAutoAdd, new String[0]);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
index 9695000..ec294b1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.phone;
+import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
@@ -54,6 +56,7 @@
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.util.time.FakeSystemClock;
import org.junit.Before;
import org.junit.Test;
@@ -115,6 +118,7 @@
private VibratorHelper mVibratorHelper;
@Mock
private BiometricUnlockLogger mLogger;
+ private final FakeSystemClock mSystemClock = new FakeSystemClock();
private BiometricUnlockController mBiometricUnlockController;
@Before
@@ -137,7 +141,9 @@
mMetricsLogger, mDumpManager, mPowerManager, mLogger,
mNotificationMediaManager, mWakefulnessLifecycle, mScreenLifecycle,
mAuthController, mStatusBarStateController,
- mSessionTracker, mLatencyTracker, mScreenOffAnimationController, mVibratorHelper);
+ mSessionTracker, mLatencyTracker, mScreenOffAnimationController, mVibratorHelper,
+ mSystemClock
+ );
mBiometricUnlockController.setKeyguardViewController(mStatusBarKeyguardViewManager);
mBiometricUnlockController.addBiometricModeListener(mBiometricModeListener);
when(mUpdateMonitor.getStrongAuthTracker()).thenReturn(mStrongAuthTracker);
@@ -200,7 +206,7 @@
verify(mKeyguardViewMediator).onWakeAndUnlocking();
assertThat(mBiometricUnlockController.getMode())
- .isEqualTo(BiometricUnlockController.MODE_WAKE_AND_UNLOCK);
+ .isEqualTo(MODE_WAKE_AND_UNLOCK);
}
@Test
@@ -437,4 +443,83 @@
// THEN wakeup the device
verify(mPowerManager).wakeUp(anyLong(), anyInt(), anyString());
}
+
+ @Test
+ public void onSideFingerprintSuccess_recentPowerButtonPress_noHaptic() {
+ // GIVEN side fingerprint enrolled, last wake reason was power button
+ when(mAuthController.isSfpsEnrolled(anyInt())).thenReturn(true);
+ when(mWakefulnessLifecycle.getLastWakeReason())
+ .thenReturn(PowerManager.WAKE_REASON_POWER_BUTTON);
+
+ // GIVEN last wake time just occurred
+ when(mWakefulnessLifecycle.getLastWakeTime()).thenReturn(mSystemClock.uptimeMillis());
+
+ // WHEN biometric fingerprint succeeds
+ givenFingerprintModeUnlockCollapsing();
+ mBiometricUnlockController.startWakeAndUnlock(BiometricSourceType.FINGERPRINT,
+ true);
+
+ // THEN DO NOT vibrate the device
+ verify(mVibratorHelper, never()).vibrateAuthSuccess(anyString());
+ }
+
+ @Test
+ public void onSideFingerprintSuccess_oldPowerButtonPress_playHaptic() {
+ // GIVEN side fingerprint enrolled, last wake reason was power button
+ when(mAuthController.isSfpsEnrolled(anyInt())).thenReturn(true);
+ when(mWakefulnessLifecycle.getLastWakeReason())
+ .thenReturn(PowerManager.WAKE_REASON_POWER_BUTTON);
+
+ // GIVEN last wake time was 500ms ago
+ when(mWakefulnessLifecycle.getLastWakeTime()).thenReturn(mSystemClock.uptimeMillis());
+ mSystemClock.advanceTime(500);
+
+ // WHEN biometric fingerprint succeeds
+ givenFingerprintModeUnlockCollapsing();
+ mBiometricUnlockController.startWakeAndUnlock(BiometricSourceType.FINGERPRINT,
+ true);
+
+ // THEN vibrate the device
+ verify(mVibratorHelper).vibrateAuthSuccess(anyString());
+ }
+
+ @Test
+ public void onSideFingerprintSuccess_recentGestureWakeUp_playHaptic() {
+ // GIVEN side fingerprint enrolled, wakeup just happened
+ when(mAuthController.isSfpsEnrolled(anyInt())).thenReturn(true);
+ when(mWakefulnessLifecycle.getLastWakeTime()).thenReturn(mSystemClock.uptimeMillis());
+
+ // GIVEN last wake reason was from a gesture
+ when(mWakefulnessLifecycle.getLastWakeReason())
+ .thenReturn(PowerManager.WAKE_REASON_GESTURE);
+
+ // WHEN biometric fingerprint succeeds
+ givenFingerprintModeUnlockCollapsing();
+ mBiometricUnlockController.startWakeAndUnlock(BiometricSourceType.FINGERPRINT,
+ true);
+
+ // THEN vibrate the device
+ verify(mVibratorHelper).vibrateAuthSuccess(anyString());
+ }
+
+ @Test
+ public void onSideFingerprintFail_alwaysPlaysHaptic() {
+ // GIVEN side fingerprint enrolled, last wake reason was recent power button
+ when(mAuthController.isSfpsEnrolled(anyInt())).thenReturn(true);
+ when(mWakefulnessLifecycle.getLastWakeReason())
+ .thenReturn(PowerManager.WAKE_REASON_POWER_BUTTON);
+ when(mWakefulnessLifecycle.getLastWakeTime()).thenReturn(mSystemClock.uptimeMillis());
+
+ // WHEN biometric fingerprint fails
+ mBiometricUnlockController.onBiometricAuthFailed(BiometricSourceType.FINGERPRINT);
+
+ // THEN always vibrate the device
+ verify(mVibratorHelper).vibrateAuthError(anyString());
+ }
+
+ private void givenFingerprintModeUnlockCollapsing() {
+ when(mUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true);
+ when(mUpdateMonitor.isDeviceInteractive()).thenReturn(true);
+ when(mKeyguardStateController.isShowing()).thenReturn(true);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
index 3a1f9b7..c8157cc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
@@ -178,8 +178,6 @@
import com.android.wm.shell.bubbles.Bubbles;
import com.android.wm.shell.startingsurface.StartingSurface;
-import dagger.Lazy;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -192,6 +190,8 @@
import java.io.PrintWriter;
import java.util.Optional;
+import dagger.Lazy;
+
@SmallTest
@RunWith(AndroidTestingRunner.class)
@RunWithLooper(setAsMainLooper = true)
@@ -380,7 +380,8 @@
}).when(mStatusBarKeyguardViewManager).addAfterKeyguardGoneRunnable(any());
mWakefulnessLifecycle =
- new WakefulnessLifecycle(mContext, mIWallpaperManager, mDumpManager);
+ new WakefulnessLifecycle(mContext, mIWallpaperManager, mFakeSystemClock,
+ mDumpManager);
mWakefulnessLifecycle.dispatchStartedWakingUp(PowerManager.WAKE_REASON_UNKNOWN);
mWakefulnessLifecycle.dispatchFinishedWakingUp();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java
index 077b41a..c843850 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java
@@ -23,6 +23,10 @@
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.res.Resources;
@@ -39,10 +43,9 @@
import com.android.systemui.doze.AlwaysOnDisplayPolicy;
import com.android.systemui.doze.DozeScreenState;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.unfold.FoldAodAnimationController;
@@ -52,6 +55,8 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -69,7 +74,6 @@
@Mock private PowerManager mPowerManager;
@Mock private TunerService mTunerService;
@Mock private BatteryController mBatteryController;
- @Mock private FeatureFlags mFeatureFlags;
@Mock private DumpManager mDumpManager;
@Mock private ScreenOffAnimationController mScreenOffAnimationController;
@Mock private FoldAodAnimationController mFoldAodAnimationController;
@@ -78,6 +82,7 @@
@Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@Mock private StatusBarStateController mStatusBarStateController;
@Mock private ConfigurationController mConfigurationController;
+ @Captor private ArgumentCaptor<BatteryStateChangeCallback> mBatteryStateChangeCallback;
/**
* The current value of PowerManager's dozeAfterScreenOff property.
@@ -113,7 +118,6 @@
mBatteryController,
mTunerService,
mDumpManager,
- mFeatureFlags,
mScreenOffAnimationController,
Optional.of(mSysUIUnfoldComponent),
mUnlockedScreenOffAnimationController,
@@ -122,7 +126,8 @@
mStatusBarStateController
);
- when(mFeatureFlags.isEnabled(Flags.LOCKSCREEN_ANIMATIONS)).thenReturn(true);
+ verify(mBatteryController).addCallback(mBatteryStateChangeCallback.capture());
+
setAodEnabledForTest(true);
setShouldControlUnlockedScreenOffForTest(true);
setDisplayNeedsBlankingForTest(false);
@@ -173,6 +178,29 @@
assertThat(mDozeParameters.getAlwaysOn()).isFalse();
}
+ @Test
+ public void testGetAlwaysOn_whenBatterySaverCallback() {
+ DozeParameters.Callback callback = mock(DozeParameters.Callback.class);
+ mDozeParameters.addCallback(callback);
+
+ when(mAmbientDisplayConfiguration.alwaysOnEnabled(anyInt())).thenReturn(true);
+ when(mBatteryController.isAodPowerSave()).thenReturn(true);
+
+ // Both lines should trigger an event
+ mDozeParameters.onTuningChanged(Settings.Secure.DOZE_ALWAYS_ON, "1");
+ mBatteryStateChangeCallback.getValue().onPowerSaveChanged(true);
+
+ verify(callback, times(2)).onAlwaysOnChange();
+ assertThat(mDozeParameters.getAlwaysOn()).isFalse();
+
+ reset(callback);
+ when(mBatteryController.isAodPowerSave()).thenReturn(false);
+ mBatteryStateChangeCallback.getValue().onPowerSaveChanged(true);
+
+ verify(callback).onAlwaysOnChange();
+ assertThat(mDozeParameters.getAlwaysOn()).isTrue();
+ }
+
/**
* PowerManager.setDozeAfterScreenOff(true) means we are not controlling screen off, and calling
* it with false means we are. Confusing, but sure - make sure that we call PowerManager with
@@ -196,17 +224,6 @@
}
@Test
- public void testControlUnlockedScreenOffAnimationDisabled_dozeAfterScreenOff() {
- when(mFeatureFlags.isEnabled(Flags.LOCKSCREEN_ANIMATIONS)).thenReturn(false);
-
- assertFalse(mDozeParameters.shouldControlUnlockedScreenOff());
-
- // Trigger the setter for the current value.
- mDozeParameters.setControlScreenOffAnimation(mDozeParameters.shouldControlScreenOff());
- assertFalse(mDozeParameters.shouldControlScreenOff());
- }
-
- @Test
public void propagatesAnimateScreenOff_noAlwaysOn() {
setAodEnabledForTest(false);
setDisplayNeedsBlankingForTest(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
index df7ee43..7ad9cc2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
@@ -16,8 +16,8 @@
package com.android.systemui.statusbar.phone;
-import static com.android.systemui.statusbar.phone.KeyguardBouncer.EXPANSION_HIDDEN;
-import static com.android.systemui.statusbar.phone.KeyguardBouncer.EXPANSION_VISIBLE;
+import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN;
+import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE;
import static com.google.common.truth.Truth.assertThat;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBypassControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBypassControllerTest.kt
new file mode 100644
index 0000000..3e90ed9
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBypassControllerTest.kt
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone
+
+import android.content.pm.PackageManager
+import android.test.suitebuilder.annotation.SmallTest
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.shade.ShadeExpansionStateManager
+import com.android.systemui.statusbar.NotificationLockscreenUserManager
+import com.android.systemui.statusbar.policy.DevicePostureController
+import com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_CLOSED
+import com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_FLIPPED
+import com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_OPENED
+import com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_UNKNOWN
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.tuner.TunerService
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.reset
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when` as whenever
+import org.mockito.junit.MockitoJUnit
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper
+class KeyguardBypassControllerTest : SysuiTestCase() {
+
+ private lateinit var keyguardBypassController: KeyguardBypassController
+ private lateinit var postureControllerCallback: DevicePostureController.Callback
+ @Mock private lateinit var tunerService: TunerService
+ @Mock private lateinit var statusBarStateController: StatusBarStateController
+ @Mock private lateinit var lockscreenUserManager: NotificationLockscreenUserManager
+ @Mock private lateinit var keyguardStateController: KeyguardStateController
+ @Mock private lateinit var shadeExpansionStateManager: ShadeExpansionStateManager
+ @Mock private lateinit var devicePostureController: DevicePostureController
+ @Mock private lateinit var dumpManager: DumpManager
+ @Mock private lateinit var packageManager: PackageManager
+ @Captor
+ private val postureCallbackCaptor =
+ ArgumentCaptor.forClass(DevicePostureController.Callback::class.java)
+ @JvmField @Rule val mockito = MockitoJUnit.rule()
+
+ @Before
+ fun setUp() {
+ context.setMockPackageManager(packageManager)
+ whenever(packageManager.hasSystemFeature(PackageManager.FEATURE_FACE)).thenReturn(true)
+ whenever(keyguardStateController.isFaceAuthEnabled).thenReturn(true)
+ }
+
+ @After
+ fun tearDown() {
+ reset(devicePostureController)
+ reset(keyguardStateController)
+ }
+
+ private fun defaultConfigPostureClosed() {
+ context.orCreateTestableResources.addOverride(
+ R.integer.config_face_auth_supported_posture,
+ DEVICE_POSTURE_CLOSED
+ )
+ initKeyguardBypassController()
+ verify(devicePostureController).addCallback(postureCallbackCaptor.capture())
+ postureControllerCallback = postureCallbackCaptor.value
+ }
+
+ private fun defaultConfigPostureOpened() {
+ context.orCreateTestableResources.addOverride(
+ R.integer.config_face_auth_supported_posture,
+ DEVICE_POSTURE_OPENED
+ )
+ initKeyguardBypassController()
+ verify(devicePostureController).addCallback(postureCallbackCaptor.capture())
+ postureControllerCallback = postureCallbackCaptor.value
+ }
+
+ private fun defaultConfigPostureFlipped() {
+ context.orCreateTestableResources.addOverride(
+ R.integer.config_face_auth_supported_posture,
+ DEVICE_POSTURE_FLIPPED
+ )
+ initKeyguardBypassController()
+ verify(devicePostureController).addCallback(postureCallbackCaptor.capture())
+ postureControllerCallback = postureCallbackCaptor.value
+ }
+
+ private fun defaultConfigPostureUnknown() {
+ context.orCreateTestableResources.addOverride(
+ R.integer.config_face_auth_supported_posture,
+ DEVICE_POSTURE_UNKNOWN
+ )
+ initKeyguardBypassController()
+ verify(devicePostureController, never()).addCallback(postureCallbackCaptor.capture())
+ }
+
+ private fun initKeyguardBypassController() {
+ keyguardBypassController =
+ KeyguardBypassController(
+ context,
+ tunerService,
+ statusBarStateController,
+ lockscreenUserManager,
+ keyguardStateController,
+ shadeExpansionStateManager,
+ devicePostureController,
+ dumpManager
+ )
+ }
+
+ @Test
+ fun configDevicePostureClosed_matchState_isPostureAllowedForFaceAuth_returnTrue() {
+ defaultConfigPostureClosed()
+
+ postureControllerCallback.onPostureChanged(DEVICE_POSTURE_CLOSED)
+
+ assertThat(keyguardBypassController.isPostureAllowedForFaceAuth()).isTrue()
+ }
+
+ @Test
+ fun configDevicePostureOpen_matchState_isPostureAllowedForFaceAuth_returnTrue() {
+ defaultConfigPostureOpened()
+
+ postureControllerCallback.onPostureChanged(DEVICE_POSTURE_OPENED)
+
+ assertThat(keyguardBypassController.isPostureAllowedForFaceAuth()).isTrue()
+ }
+
+ @Test
+ fun configDevicePostureFlipped_matchState_isPostureAllowedForFaceAuth_returnTrue() {
+ defaultConfigPostureFlipped()
+
+ postureControllerCallback.onPostureChanged(DEVICE_POSTURE_FLIPPED)
+
+ assertThat(keyguardBypassController.isPostureAllowedForFaceAuth()).isTrue()
+ }
+
+ @Test
+ fun configDevicePostureClosed_changeOpened_isPostureAllowedForFaceAuth_returnFalse() {
+ defaultConfigPostureClosed()
+
+ postureControllerCallback.onPostureChanged(DEVICE_POSTURE_OPENED)
+
+ assertThat(keyguardBypassController.isPostureAllowedForFaceAuth()).isFalse()
+ }
+
+ @Test
+ fun configDevicePostureClosed_changeFlipped_isPostureAllowedForFaceAuth_returnFalse() {
+ defaultConfigPostureClosed()
+
+ postureControllerCallback.onPostureChanged(DEVICE_POSTURE_FLIPPED)
+
+ assertThat(keyguardBypassController.isPostureAllowedForFaceAuth()).isFalse()
+ }
+
+ @Test
+ fun configDevicePostureOpened_changeClosed_isPostureAllowedForFaceAuth_returnFalse() {
+ defaultConfigPostureOpened()
+
+ postureControllerCallback.onPostureChanged(DEVICE_POSTURE_CLOSED)
+
+ assertThat(keyguardBypassController.isPostureAllowedForFaceAuth()).isFalse()
+ }
+
+ @Test
+ fun configDevicePostureOpened_changeFlipped_isPostureAllowedForFaceAuth_returnFalse() {
+ defaultConfigPostureOpened()
+
+ postureControllerCallback.onPostureChanged(DEVICE_POSTURE_FLIPPED)
+
+ assertThat(keyguardBypassController.isPostureAllowedForFaceAuth()).isFalse()
+ }
+
+ @Test
+ fun configDevicePostureFlipped_changeClosed_isPostureAllowedForFaceAuth_returnFalse() {
+ defaultConfigPostureFlipped()
+
+ postureControllerCallback.onPostureChanged(DEVICE_POSTURE_CLOSED)
+
+ assertThat(keyguardBypassController.isPostureAllowedForFaceAuth()).isFalse()
+ }
+
+ @Test
+ fun configDevicePostureFlipped_changeOpened_isPostureAllowedForFaceAuth_returnFalse() {
+ defaultConfigPostureFlipped()
+
+ postureControllerCallback.onPostureChanged(DEVICE_POSTURE_OPENED)
+
+ assertThat(keyguardBypassController.isPostureAllowedForFaceAuth()).isFalse()
+ }
+
+ @Test
+ fun defaultConfigPostureClosed_canOverrideByPassAlways_shouldReturnFalse() {
+ context.orCreateTestableResources.addOverride(
+ R.integer.config_face_unlock_bypass_override,
+ 1 /* FACE_UNLOCK_BYPASS_ALWAYS */
+ )
+
+ defaultConfigPostureClosed()
+
+ postureControllerCallback.onPostureChanged(DEVICE_POSTURE_OPENED)
+
+ assertThat(keyguardBypassController.bypassEnabled).isFalse()
+ }
+
+ @Test
+ fun defaultConfigPostureUnknown_canNotOverrideByPassAlways_shouldReturnTrue() {
+ context.orCreateTestableResources.addOverride(
+ R.integer.config_face_unlock_bypass_override,
+ 1 /* FACE_UNLOCK_BYPASS_ALWAYS */
+ )
+
+ defaultConfigPostureUnknown()
+
+ assertThat(keyguardBypassController.bypassEnabled).isTrue()
+ }
+
+ @Test
+ fun defaultConfigPostureUnknown_canNotOverrideByPassNever_shouldReturnFalse() {
+ context.orCreateTestableResources.addOverride(
+ R.integer.config_face_unlock_bypass_override,
+ 2 /* FACE_UNLOCK_BYPASS_NEVER */
+ )
+
+ defaultConfigPostureUnknown()
+
+ assertThat(keyguardBypassController.bypassEnabled).isFalse()
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index e475905..c7a0582 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -58,6 +58,7 @@
import com.android.systemui.animation.ShadeInterpolation;
import com.android.systemui.dock.DockManager;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
+import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants;
import com.android.systemui.scrim.ScrimView;
import com.android.systemui.statusbar.policy.FakeConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -1562,7 +1563,7 @@
@Test
public void transitionToDreaming() {
mScrimController.setRawPanelExpansionFraction(0f);
- mScrimController.setBouncerHiddenFraction(KeyguardBouncer.EXPANSION_HIDDEN);
+ mScrimController.setBouncerHiddenFraction(KeyguardBouncerConstants.EXPANSION_HIDDEN);
mScrimController.transitionTo(ScrimState.DREAMING);
finishAnimationsImmediately();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImplTest.kt
new file mode 100644
index 0000000..3bc288a2
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImplTest.kt
@@ -0,0 +1,309 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone
+
+import android.os.UserHandle
+import androidx.test.filters.SmallTest
+import com.android.internal.statusbar.StatusBarIcon
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.phone.StatusBarIconController.TAG_PRIMARY
+import com.android.systemui.statusbar.phone.StatusBarIconControllerImpl.EXTERNAL_SLOT_SUFFIX
+import com.android.systemui.util.mockito.mock
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.mockito.Mockito.verify
+
+@SmallTest
+class StatusBarIconControllerImplTest : SysuiTestCase() {
+
+ private lateinit var underTest: StatusBarIconControllerImpl
+
+ private lateinit var iconList: StatusBarIconList
+ private val iconGroup: StatusBarIconController.IconManager = mock()
+
+ @Before
+ fun setUp() {
+ iconList = StatusBarIconList(arrayOf())
+ underTest =
+ StatusBarIconControllerImpl(
+ context,
+ mock(),
+ mock(),
+ mock(),
+ mock(),
+ mock(),
+ iconList,
+ mock(),
+ )
+ underTest.addIconGroup(iconGroup)
+ }
+
+ /** Regression test for b/255428281. */
+ @Test
+ fun internalAndExternalIconWithSameName_bothDisplayed() {
+ val slotName = "mute"
+
+ // Internal
+ underTest.setIcon(slotName, /* resourceId= */ 10, "contentDescription")
+
+ // External
+ val externalIcon =
+ StatusBarIcon(
+ "external.package",
+ UserHandle.ALL,
+ /* iconId= */ 2,
+ /* iconLevel= */ 0,
+ /* number= */ 0,
+ "contentDescription",
+ )
+ underTest.setIcon(slotName, externalIcon)
+
+ assertThat(iconList.slots).hasSize(2)
+ // Whichever was added last comes first
+ assertThat(iconList.slots[0].name).isEqualTo(slotName + EXTERNAL_SLOT_SUFFIX)
+ assertThat(iconList.slots[1].name).isEqualTo(slotName)
+ assertThat(iconList.slots[0].hasIconsInSlot()).isTrue()
+ assertThat(iconList.slots[1].hasIconsInSlot()).isTrue()
+ }
+
+ /** Regression test for b/255428281. */
+ @Test
+ fun internalAndExternalIconWithSameName_externalRemoved_viaRemoveIcon_internalStays() {
+ val slotName = "mute"
+
+ // Internal
+ underTest.setIcon(slotName, /* resourceId= */ 10, "contentDescription")
+
+ // External
+ underTest.setIcon(slotName, createExternalIcon())
+
+ // WHEN the external icon is removed via #removeIcon
+ underTest.removeIcon(slotName)
+
+ // THEN the external icon is removed but the internal icon remains
+ // Note: [StatusBarIconList] never removes slots from its list, it just sets the holder for
+ // the slot to null when an icon is removed.
+ assertThat(iconList.slots).hasSize(2)
+ assertThat(iconList.slots[0].name).isEqualTo(slotName + EXTERNAL_SLOT_SUFFIX)
+ assertThat(iconList.slots[1].name).isEqualTo(slotName)
+ assertThat(iconList.slots[0].hasIconsInSlot()).isFalse() // Indicates removal
+ assertThat(iconList.slots[1].hasIconsInSlot()).isTrue()
+
+ verify(iconGroup).onRemoveIcon(0)
+ }
+
+ /** Regression test for b/255428281. */
+ @Test
+ fun internalAndExternalIconWithSameName_externalRemoved_viaRemoveAll_internalStays() {
+ val slotName = "mute"
+
+ // Internal
+ underTest.setIcon(slotName, /* resourceId= */ 10, "contentDescription")
+
+ // External
+ underTest.setIcon(slotName, createExternalIcon())
+
+ // WHEN the external icon is removed via #removeAllIconsForExternalSlot
+ underTest.removeAllIconsForExternalSlot(slotName)
+
+ // THEN the external icon is removed but the internal icon remains
+ assertThat(iconList.slots).hasSize(2)
+ assertThat(iconList.slots[0].name).isEqualTo(slotName + EXTERNAL_SLOT_SUFFIX)
+ assertThat(iconList.slots[1].name).isEqualTo(slotName)
+ assertThat(iconList.slots[0].hasIconsInSlot()).isFalse() // Indicates removal
+ assertThat(iconList.slots[1].hasIconsInSlot()).isTrue()
+
+ verify(iconGroup).onRemoveIcon(0)
+ }
+
+ /** Regression test for b/255428281. */
+ @Test
+ fun internalAndExternalIconWithSameName_externalRemoved_viaSetNull_internalStays() {
+ val slotName = "mute"
+
+ // Internal
+ underTest.setIcon(slotName, /* resourceId= */ 10, "contentDescription")
+
+ // External
+ underTest.setIcon(slotName, createExternalIcon())
+
+ // WHEN the external icon is removed via a #setIcon(null)
+ underTest.setIcon(slotName, /* icon= */ null)
+
+ // THEN the external icon is removed but the internal icon remains
+ assertThat(iconList.slots).hasSize(2)
+ assertThat(iconList.slots[0].name).isEqualTo(slotName + EXTERNAL_SLOT_SUFFIX)
+ assertThat(iconList.slots[1].name).isEqualTo(slotName)
+ assertThat(iconList.slots[0].hasIconsInSlot()).isFalse() // Indicates removal
+ assertThat(iconList.slots[1].hasIconsInSlot()).isTrue()
+
+ verify(iconGroup).onRemoveIcon(0)
+ }
+
+ /** Regression test for b/255428281. */
+ @Test
+ fun internalAndExternalIconWithSameName_internalRemoved_viaRemove_externalStays() {
+ val slotName = "mute"
+
+ // Internal
+ underTest.setIcon(slotName, /* resourceId= */ 10, "contentDescription")
+
+ // External
+ underTest.setIcon(slotName, createExternalIcon())
+
+ // WHEN the internal icon is removed via #removeIcon
+ underTest.removeIcon(slotName, /* tag= */ 0)
+
+ // THEN the external icon is removed but the internal icon remains
+ assertThat(iconList.slots).hasSize(2)
+ assertThat(iconList.slots[0].name).isEqualTo(slotName + EXTERNAL_SLOT_SUFFIX)
+ assertThat(iconList.slots[1].name).isEqualTo(slotName)
+ assertThat(iconList.slots[0].hasIconsInSlot()).isTrue()
+ assertThat(iconList.slots[1].hasIconsInSlot()).isFalse() // Indicates removal
+
+ verify(iconGroup).onRemoveIcon(1)
+ }
+
+ /** Regression test for b/255428281. */
+ @Test
+ fun internalAndExternalIconWithSameName_internalRemoved_viaRemoveAll_externalStays() {
+ val slotName = "mute"
+
+ // Internal
+ underTest.setIcon(slotName, /* resourceId= */ 10, "contentDescription")
+
+ // External
+ underTest.setIcon(slotName, createExternalIcon())
+
+ // WHEN the internal icon is removed via #removeAllIconsForSlot
+ underTest.removeAllIconsForSlot(slotName)
+
+ // THEN the external icon is removed but the internal icon remains
+ assertThat(iconList.slots).hasSize(2)
+ assertThat(iconList.slots[0].name).isEqualTo(slotName + EXTERNAL_SLOT_SUFFIX)
+ assertThat(iconList.slots[1].name).isEqualTo(slotName)
+ assertThat(iconList.slots[0].hasIconsInSlot()).isTrue()
+ assertThat(iconList.slots[1].hasIconsInSlot()).isFalse() // Indicates removal
+
+ verify(iconGroup).onRemoveIcon(1)
+ }
+
+ /** Regression test for b/255428281. */
+ @Test
+ fun internalAndExternalIconWithSameName_internalUpdatedIndependently() {
+ val slotName = "mute"
+
+ // Internal
+ underTest.setIcon(slotName, /* resourceId= */ 10, "contentDescription")
+
+ // External
+ val startingExternalIcon =
+ StatusBarIcon(
+ "external.package",
+ UserHandle.ALL,
+ /* iconId= */ 20,
+ /* iconLevel= */ 0,
+ /* number= */ 0,
+ "externalDescription",
+ )
+ underTest.setIcon(slotName, startingExternalIcon)
+
+ // WHEN the internal icon is updated
+ underTest.setIcon(slotName, /* resourceId= */ 11, "newContentDescription")
+
+ // THEN only the internal slot gets the updates
+ val internalSlot = iconList.slots[1]
+ val internalHolder = internalSlot.getHolderForTag(TAG_PRIMARY)!!
+ assertThat(internalSlot.name).isEqualTo(slotName)
+ assertThat(internalHolder.icon!!.contentDescription).isEqualTo("newContentDescription")
+ assertThat(internalHolder.icon!!.icon.resId).isEqualTo(11)
+
+ // And the external slot has its own values
+ val externalSlot = iconList.slots[0]
+ val externalHolder = externalSlot.getHolderForTag(TAG_PRIMARY)!!
+ assertThat(externalSlot.name).isEqualTo(slotName + EXTERNAL_SLOT_SUFFIX)
+ assertThat(externalHolder.icon!!.contentDescription).isEqualTo("externalDescription")
+ assertThat(externalHolder.icon!!.icon.resId).isEqualTo(20)
+ }
+
+ /** Regression test for b/255428281. */
+ @Test
+ fun internalAndExternalIconWithSameName_externalUpdatedIndependently() {
+ val slotName = "mute"
+
+ // Internal
+ underTest.setIcon(slotName, /* resourceId= */ 10, "contentDescription")
+
+ // External
+ val startingExternalIcon =
+ StatusBarIcon(
+ "external.package",
+ UserHandle.ALL,
+ /* iconId= */ 20,
+ /* iconLevel= */ 0,
+ /* number= */ 0,
+ "externalDescription",
+ )
+ underTest.setIcon(slotName, startingExternalIcon)
+
+ // WHEN the external icon is updated
+ val newExternalIcon =
+ StatusBarIcon(
+ "external.package",
+ UserHandle.ALL,
+ /* iconId= */ 21,
+ /* iconLevel= */ 0,
+ /* number= */ 0,
+ "newExternalDescription",
+ )
+ underTest.setIcon(slotName, newExternalIcon)
+
+ // THEN only the external slot gets the updates
+ val externalSlot = iconList.slots[0]
+ val externalHolder = externalSlot.getHolderForTag(TAG_PRIMARY)!!
+ assertThat(externalSlot.name).isEqualTo(slotName + EXTERNAL_SLOT_SUFFIX)
+ assertThat(externalHolder.icon!!.contentDescription).isEqualTo("newExternalDescription")
+ assertThat(externalHolder.icon!!.icon.resId).isEqualTo(21)
+
+ // And the internal slot has its own values
+ val internalSlot = iconList.slots[1]
+ val internalHolder = internalSlot.getHolderForTag(TAG_PRIMARY)!!
+ assertThat(internalSlot.name).isEqualTo(slotName)
+ assertThat(internalHolder.icon!!.contentDescription).isEqualTo("contentDescription")
+ assertThat(internalHolder.icon!!.icon.resId).isEqualTo(10)
+ }
+
+ @Test
+ fun externalSlot_alreadyEndsWithSuffix_suffixNotAddedTwice() {
+ underTest.setIcon("myslot$EXTERNAL_SLOT_SUFFIX", createExternalIcon())
+
+ assertThat(iconList.slots).hasSize(1)
+ assertThat(iconList.slots[0].name).isEqualTo("myslot$EXTERNAL_SLOT_SUFFIX")
+ }
+
+ private fun createExternalIcon(): StatusBarIcon {
+ return StatusBarIcon(
+ "external.package",
+ UserHandle.ALL,
+ /* iconId= */ 2,
+ /* iconLevel= */ 0,
+ /* number= */ 0,
+ "contentDescription",
+ )
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index 04a6700..dea4a7d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -17,6 +17,8 @@
package com.android.systemui.statusbar.phone;
import static com.android.systemui.flags.Flags.MODERN_BOUNCER;
+import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN;
+import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
@@ -37,6 +39,8 @@
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewRootImpl;
+import android.window.BackEvent;
+import android.window.OnBackAnimationCallback;
import android.window.OnBackInvokedCallback;
import android.window.OnBackInvokedDispatcher;
import android.window.WindowOnBackInvokedDispatcher;
@@ -54,6 +58,7 @@
import com.android.systemui.dock.DockManager;
import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
import com.android.systemui.keyguard.data.BouncerView;
import com.android.systemui.keyguard.data.BouncerViewDelegate;
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
@@ -118,16 +123,19 @@
@Mock private AlternateBouncerInteractor mAlternateBouncerInteractor;
@Mock private BouncerView mBouncerView;
@Mock private BouncerViewDelegate mBouncerViewDelegate;
+ @Mock private OnBackAnimationCallback mBouncerViewDelegateBackCallback;
private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
private KeyguardBouncer.PrimaryBouncerExpansionCallback mBouncerExpansionCallback;
private FakeKeyguardStateController mKeyguardStateController =
spy(new FakeKeyguardStateController());
- @Mock private ViewRootImpl mViewRootImpl;
- @Mock private WindowOnBackInvokedDispatcher mOnBackInvokedDispatcher;
+ @Mock
+ private ViewRootImpl mViewRootImpl;
+ @Mock
+ private WindowOnBackInvokedDispatcher mOnBackInvokedDispatcher;
@Captor
- private ArgumentCaptor<OnBackInvokedCallback> mOnBackInvokedCallback;
+ private ArgumentCaptor<OnBackInvokedCallback> mBackCallbackCaptor;
@Before
@@ -138,6 +146,10 @@
when(mKeyguardMessageAreaFactory.create(any(KeyguardMessageArea.class)))
.thenReturn(mKeyguardMessageAreaController);
when(mBouncerView.getDelegate()).thenReturn(mBouncerViewDelegate);
+ when(mBouncerViewDelegate.getBackCallback()).thenReturn(mBouncerViewDelegateBackCallback);
+ when(mFeatureFlags
+ .isEnabled(Flags.WM_ENABLE_PREDICTIVE_BACK_BOUNCER_ANIM))
+ .thenReturn(true);
when(mFeatureFlags.isEnabled(MODERN_BOUNCER)).thenReturn(true);
@@ -191,7 +203,8 @@
@Test
public void dismissWithAction_AfterKeyguardGoneSetToFalse() {
OnDismissAction action = () -> false;
- Runnable cancelAction = () -> {};
+ Runnable cancelAction = () -> {
+ };
mStatusBarKeyguardViewManager.dismissWithAction(
action, cancelAction, false /* afterKeyguardGone */);
verify(mPrimaryBouncerInteractor).setDismissAction(eq(action), eq(cancelAction));
@@ -255,7 +268,7 @@
when(mPrimaryBouncerInteractor.isInTransit()).thenReturn(true);
mStatusBarKeyguardViewManager.onPanelExpansionChanged(EXPANSION_EVENT);
- verify(mPrimaryBouncerInteractor).setPanelExpansion(eq(KeyguardBouncer.EXPANSION_HIDDEN));
+ verify(mPrimaryBouncerInteractor).setPanelExpansion(eq(EXPANSION_HIDDEN));
}
@Test
@@ -283,7 +296,7 @@
.thenReturn(BiometricUnlockController.MODE_WAKE_AND_UNLOCK);
mStatusBarKeyguardViewManager.onPanelExpansionChanged(
expansionEvent(
- /* fraction= */ KeyguardBouncer.EXPANSION_VISIBLE,
+ /* fraction= */ EXPANSION_VISIBLE,
/* expanded= */ true,
/* tracking= */ false));
verify(mPrimaryBouncerInteractor, never()).setPanelExpansion(anyFloat());
@@ -300,7 +313,7 @@
.thenReturn(BiometricUnlockController.MODE_DISMISS_BOUNCER);
mStatusBarKeyguardViewManager.onPanelExpansionChanged(
expansionEvent(
- /* fraction= */ KeyguardBouncer.EXPANSION_VISIBLE,
+ /* fraction= */ EXPANSION_VISIBLE,
/* expanded= */ true,
/* tracking= */ false));
verify(mPrimaryBouncerInteractor, never()).setPanelExpansion(anyFloat());
@@ -311,7 +324,7 @@
when(mKeyguardStateController.isOccluded()).thenReturn(true);
mStatusBarKeyguardViewManager.onPanelExpansionChanged(
expansionEvent(
- /* fraction= */ KeyguardBouncer.EXPANSION_VISIBLE,
+ /* fraction= */ EXPANSION_VISIBLE,
/* expanded= */ true,
/* tracking= */ false));
verify(mPrimaryBouncerInteractor, never()).setPanelExpansion(anyFloat());
@@ -328,7 +341,7 @@
.thenReturn(BiometricUnlockController.MODE_SHOW_BOUNCER);
mStatusBarKeyguardViewManager.onPanelExpansionChanged(
expansionEvent(
- /* fraction= */ KeyguardBouncer.EXPANSION_VISIBLE,
+ /* fraction= */ EXPANSION_VISIBLE,
/* expanded= */ true,
/* tracking= */ false));
verify(mPrimaryBouncerInteractor, never()).setPanelExpansion(anyFloat());
@@ -339,7 +352,7 @@
when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE_LOCKED);
mStatusBarKeyguardViewManager.onPanelExpansionChanged(
expansionEvent(
- /* fraction= */ KeyguardBouncer.EXPANSION_VISIBLE,
+ /* fraction= */ EXPANSION_VISIBLE,
/* expanded= */ true,
/* tracking= */ false));
verify(mPrimaryBouncerInteractor, never()).setPanelExpansion(anyFloat());
@@ -539,12 +552,12 @@
mBouncerExpansionCallback.onVisibilityChanged(true);
verify(mOnBackInvokedDispatcher).registerOnBackInvokedCallback(
eq(OnBackInvokedDispatcher.PRIORITY_OVERLAY),
- mOnBackInvokedCallback.capture());
+ mBackCallbackCaptor.capture());
/* verify that the same callback is unregistered when the bouncer becomes invisible */
mBouncerExpansionCallback.onVisibilityChanged(false);
verify(mOnBackInvokedDispatcher).unregisterOnBackInvokedCallback(
- eq(mOnBackInvokedCallback.getValue()));
+ eq(mBackCallbackCaptor.getValue()));
}
@Test
@@ -553,18 +566,63 @@
/* capture the predictive back callback during registration */
verify(mOnBackInvokedDispatcher).registerOnBackInvokedCallback(
eq(OnBackInvokedDispatcher.PRIORITY_OVERLAY),
- mOnBackInvokedCallback.capture());
+ mBackCallbackCaptor.capture());
when(mPrimaryBouncerInteractor.isFullyShowing()).thenReturn(true);
when(mCentralSurfaces.shouldKeyguardHideImmediately()).thenReturn(true);
/* invoke the back callback directly */
- mOnBackInvokedCallback.getValue().onBackInvoked();
+ mBackCallbackCaptor.getValue().onBackInvoked();
/* verify that the bouncer will be hidden as a result of the invocation */
verify(mCentralSurfaces).setBouncerShowing(eq(false));
}
@Test
+ public void testPredictiveBackCallback_noBackAnimationForFullScreenBouncer() {
+ when(mKeyguardSecurityModel.getSecurityMode(anyInt()))
+ .thenReturn(KeyguardSecurityModel.SecurityMode.SimPin);
+ mBouncerExpansionCallback.onVisibilityChanged(true);
+ /* capture the predictive back callback during registration */
+ verify(mOnBackInvokedDispatcher).registerOnBackInvokedCallback(
+ eq(OnBackInvokedDispatcher.PRIORITY_OVERLAY),
+ mBackCallbackCaptor.capture());
+ assertTrue(mBackCallbackCaptor.getValue() instanceof OnBackAnimationCallback);
+
+ OnBackAnimationCallback backCallback =
+ (OnBackAnimationCallback) mBackCallbackCaptor.getValue();
+
+ BackEvent event = new BackEvent(0, 0, 0, BackEvent.EDGE_LEFT);
+ backCallback.onBackStarted(event);
+ verify(mBouncerViewDelegateBackCallback, never()).onBackStarted(any());
+ }
+
+ @Test
+ public void testPredictiveBackCallback_forwardsBackDispatches() {
+ mBouncerExpansionCallback.onVisibilityChanged(true);
+ /* capture the predictive back callback during registration */
+ verify(mOnBackInvokedDispatcher).registerOnBackInvokedCallback(
+ eq(OnBackInvokedDispatcher.PRIORITY_OVERLAY),
+ mBackCallbackCaptor.capture());
+ assertTrue(mBackCallbackCaptor.getValue() instanceof OnBackAnimationCallback);
+
+ OnBackAnimationCallback backCallback =
+ (OnBackAnimationCallback) mBackCallbackCaptor.getValue();
+
+ BackEvent event = new BackEvent(0, 0, 0, BackEvent.EDGE_LEFT);
+ backCallback.onBackStarted(event);
+ verify(mBouncerViewDelegateBackCallback).onBackStarted(eq(event));
+
+ backCallback.onBackProgressed(event);
+ verify(mBouncerViewDelegateBackCallback).onBackProgressed(eq(event));
+
+ backCallback.onBackInvoked();
+ verify(mBouncerViewDelegateBackCallback).onBackInvoked();
+
+ backCallback.onBackCancelled();
+ verify(mBouncerViewDelegateBackCallback).onBackCancelled();
+ }
+
+ @Test
public void testReportBouncerOnDreamWhenVisible() {
mBouncerExpansionCallback.onVisibilityChanged(true);
verify(mCentralSurfaces).setBouncerShowingOverDream(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest_Old.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest_Old.java
index a9c55fa..0605b8d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest_Old.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest_Old.java
@@ -17,6 +17,8 @@
package com.android.systemui.statusbar.phone;
import static com.android.systemui.flags.Flags.MODERN_BOUNCER;
+import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN;
+import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
@@ -261,7 +263,7 @@
when(mPrimaryBouncer.inTransit()).thenReturn(true);
mStatusBarKeyguardViewManager.onPanelExpansionChanged(EXPANSION_EVENT);
- verify(mPrimaryBouncer).setExpansion(eq(KeyguardBouncer.EXPANSION_HIDDEN));
+ verify(mPrimaryBouncer).setExpansion(eq(EXPANSION_HIDDEN));
}
@Test
@@ -289,7 +291,7 @@
.thenReturn(BiometricUnlockController.MODE_WAKE_AND_UNLOCK);
mStatusBarKeyguardViewManager.onPanelExpansionChanged(
expansionEvent(
- /* fraction= */ KeyguardBouncer.EXPANSION_VISIBLE,
+ /* fraction= */ EXPANSION_VISIBLE,
/* expanded= */ true,
/* tracking= */ false));
verify(mPrimaryBouncer, never()).setExpansion(anyFloat());
@@ -306,7 +308,7 @@
.thenReturn(BiometricUnlockController.MODE_DISMISS_BOUNCER);
mStatusBarKeyguardViewManager.onPanelExpansionChanged(
expansionEvent(
- /* fraction= */ KeyguardBouncer.EXPANSION_VISIBLE,
+ /* fraction= */ EXPANSION_VISIBLE,
/* expanded= */ true,
/* tracking= */ false));
verify(mPrimaryBouncer, never()).setExpansion(anyFloat());
@@ -317,7 +319,7 @@
when(mKeyguardStateController.isOccluded()).thenReturn(true);
mStatusBarKeyguardViewManager.onPanelExpansionChanged(
expansionEvent(
- /* fraction= */ KeyguardBouncer.EXPANSION_VISIBLE,
+ /* fraction= */ EXPANSION_VISIBLE,
/* expanded= */ true,
/* tracking= */ false));
verify(mPrimaryBouncer, never()).setExpansion(anyFloat());
@@ -334,7 +336,7 @@
.thenReturn(BiometricUnlockController.MODE_SHOW_BOUNCER);
mStatusBarKeyguardViewManager.onPanelExpansionChanged(
expansionEvent(
- /* fraction= */ KeyguardBouncer.EXPANSION_VISIBLE,
+ /* fraction= */ EXPANSION_VISIBLE,
/* expanded= */ true,
/* tracking= */ false));
verify(mPrimaryBouncer, never()).setExpansion(anyFloat());
@@ -345,7 +347,7 @@
when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE_LOCKED);
mStatusBarKeyguardViewManager.onPanelExpansionChanged(
expansionEvent(
- /* fraction= */ KeyguardBouncer.EXPANSION_VISIBLE,
+ /* fraction= */ EXPANSION_VISIBLE,
/* expanded= */ true,
/* tracking= */ false));
verify(mPrimaryBouncer, never()).setExpansion(anyFloat());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt
index 5d377a8..0859d14 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt
@@ -34,6 +34,8 @@
import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.MobileConnectionsRepositoryImpl
import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
+import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
+import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoModeWifiDataSource
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.kotlinArgumentCaptor
import com.android.systemui.util.mockito.mock
@@ -71,8 +73,10 @@
private lateinit var underTest: MobileRepositorySwitcher
private lateinit var realRepo: MobileConnectionsRepositoryImpl
private lateinit var demoRepo: DemoMobileConnectionsRepository
- private lateinit var mockDataSource: DemoModeMobileConnectionDataSource
+ private lateinit var mobileDataSource: DemoModeMobileConnectionDataSource
+ private lateinit var wifiDataSource: DemoModeWifiDataSource
private lateinit var logFactory: TableLogBufferFactory
+ private lateinit var wifiRepository: FakeWifiRepository
@Mock private lateinit var connectivityManager: ConnectivityManager
@Mock private lateinit var subscriptionManager: SubscriptionManager
@@ -96,10 +100,15 @@
// Never start in demo mode
whenever(demoModeController.isInDemoMode).thenReturn(false)
- mockDataSource =
+ mobileDataSource =
mock<DemoModeMobileConnectionDataSource>().also {
whenever(it.mobileEvents).thenReturn(fakeNetworkEventsFlow)
}
+ wifiDataSource =
+ mock<DemoModeWifiDataSource>().also {
+ whenever(it.wifiEvents).thenReturn(MutableStateFlow(null))
+ }
+ wifiRepository = FakeWifiRepository()
realRepo =
MobileConnectionsRepositoryImpl(
@@ -113,12 +122,14 @@
context,
IMMEDIATE,
scope,
+ wifiRepository,
mock(),
)
demoRepo =
DemoMobileConnectionsRepository(
- dataSource = mockDataSource,
+ mobileDataSource = mobileDataSource,
+ wifiDataSource = wifiDataSource,
scope = scope,
context = context,
logFactory = logFactory,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt
index 2102085..6989b514 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt
@@ -29,6 +29,8 @@
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel
import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
+import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoModeWifiDataSource
+import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.FakeWifiEventModel
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.FakeSystemClock
@@ -63,10 +65,12 @@
private val testScope = TestScope(testDispatcher)
private val fakeNetworkEventFlow = MutableStateFlow<FakeNetworkEventModel?>(null)
+ private val fakeWifiEventFlow = MutableStateFlow<FakeWifiEventModel?>(null)
private lateinit var connectionsRepo: DemoMobileConnectionsRepository
private lateinit var underTest: DemoMobileConnectionRepository
private lateinit var mockDataSource: DemoModeMobileConnectionDataSource
+ private lateinit var mockWifiDataSource: DemoModeWifiDataSource
@Before
fun setUp() {
@@ -75,10 +79,15 @@
mock<DemoModeMobileConnectionDataSource>().also {
whenever(it.mobileEvents).thenReturn(fakeNetworkEventFlow)
}
+ mockWifiDataSource =
+ mock<DemoModeWifiDataSource>().also {
+ whenever(it.wifiEvents).thenReturn(fakeWifiEventFlow)
+ }
connectionsRepo =
DemoMobileConnectionsRepository(
- dataSource = mockDataSource,
+ mobileDataSource = mockDataSource,
+ wifiDataSource = mockWifiDataSource,
scope = testScope.backgroundScope,
context = context,
logFactory = logFactory,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt
index cdbe75e..9d16b7fe 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt
@@ -32,6 +32,8 @@
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel.MobileDisabled
import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
+import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoModeWifiDataSource
+import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.FakeWifiEventModel
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.FakeSystemClock
@@ -57,21 +59,28 @@
private val testScope = TestScope(testDispatcher)
private val fakeNetworkEventFlow = MutableStateFlow<FakeNetworkEventModel?>(null)
+ private val fakeWifiEventFlow = MutableStateFlow<FakeWifiEventModel?>(null)
private lateinit var underTest: DemoMobileConnectionsRepository
- private lateinit var mockDataSource: DemoModeMobileConnectionDataSource
+ private lateinit var mobileDataSource: DemoModeMobileConnectionDataSource
+ private lateinit var wifiDataSource: DemoModeWifiDataSource
@Before
fun setUp() {
// The data source only provides one API, so we can mock it with a flow here for convenience
- mockDataSource =
+ mobileDataSource =
mock<DemoModeMobileConnectionDataSource>().also {
whenever(it.mobileEvents).thenReturn(fakeNetworkEventFlow)
}
+ wifiDataSource =
+ mock<DemoModeWifiDataSource>().also {
+ whenever(it.wifiEvents).thenReturn(fakeWifiEventFlow)
+ }
underTest =
DemoMobileConnectionsRepository(
- dataSource = mockDataSource,
+ mobileDataSource = mobileDataSource,
+ wifiDataSource = wifiDataSource,
scope = testScope.backgroundScope,
context = context,
logFactory = logFactory,
@@ -97,6 +106,22 @@
}
@Test
+ fun `wifi carrier merged event - create new subscription`() =
+ testScope.runTest {
+ var latest: List<SubscriptionModel>? = null
+ val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
+
+ assertThat(latest).isEmpty()
+
+ fakeWifiEventFlow.value = validCarrierMergedEvent(subId = 5)
+
+ assertThat(latest).hasSize(1)
+ assertThat(latest!![0].subscriptionId).isEqualTo(5)
+
+ job.cancel()
+ }
+
+ @Test
fun `network event - reuses subscription when same Id`() =
testScope.runTest {
var latest: List<SubscriptionModel>? = null
@@ -119,6 +144,28 @@
}
@Test
+ fun `wifi carrier merged event - reuses subscription when same Id`() =
+ testScope.runTest {
+ var latest: List<SubscriptionModel>? = null
+ val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
+
+ assertThat(latest).isEmpty()
+
+ fakeWifiEventFlow.value = validCarrierMergedEvent(subId = 5, level = 1)
+
+ assertThat(latest).hasSize(1)
+ assertThat(latest!![0].subscriptionId).isEqualTo(5)
+
+ // Second network event comes in with the same subId, does not create a new subscription
+ fakeWifiEventFlow.value = validCarrierMergedEvent(subId = 5, level = 2)
+
+ assertThat(latest).hasSize(1)
+ assertThat(latest!![0].subscriptionId).isEqualTo(5)
+
+ job.cancel()
+ }
+
+ @Test
fun `multiple subscriptions`() =
testScope.runTest {
var latest: List<SubscriptionModel>? = null
@@ -133,6 +180,35 @@
}
@Test
+ fun `mobile subscription and carrier merged subscription`() =
+ testScope.runTest {
+ var latest: List<SubscriptionModel>? = null
+ val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
+
+ fakeNetworkEventFlow.value = validMobileEvent(subId = 1)
+ fakeWifiEventFlow.value = validCarrierMergedEvent(subId = 5)
+
+ assertThat(latest).hasSize(2)
+
+ job.cancel()
+ }
+
+ @Test
+ fun `multiple mobile subscriptions and carrier merged subscription`() =
+ testScope.runTest {
+ var latest: List<SubscriptionModel>? = null
+ val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
+
+ fakeNetworkEventFlow.value = validMobileEvent(subId = 1)
+ fakeNetworkEventFlow.value = validMobileEvent(subId = 2)
+ fakeWifiEventFlow.value = validCarrierMergedEvent(subId = 3)
+
+ assertThat(latest).hasSize(3)
+
+ job.cancel()
+ }
+
+ @Test
fun `mobile disabled event - disables connection - subId specified - single conn`() =
testScope.runTest {
var latest: List<SubscriptionModel>? = null
@@ -194,6 +270,112 @@
job.cancel()
}
+ @Test
+ fun `wifi network updates to disabled - carrier merged connection removed`() =
+ testScope.runTest {
+ var latest: List<SubscriptionModel>? = null
+ val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
+
+ fakeWifiEventFlow.value = validCarrierMergedEvent(subId = 1)
+
+ assertThat(latest).hasSize(1)
+
+ fakeWifiEventFlow.value = FakeWifiEventModel.WifiDisabled
+
+ assertThat(latest).isEmpty()
+
+ job.cancel()
+ }
+
+ @Test
+ fun `wifi network updates to active - carrier merged connection removed`() =
+ testScope.runTest {
+ var latest: List<SubscriptionModel>? = null
+ val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
+
+ fakeWifiEventFlow.value = validCarrierMergedEvent(subId = 1)
+
+ assertThat(latest).hasSize(1)
+
+ fakeWifiEventFlow.value =
+ FakeWifiEventModel.Wifi(
+ level = 1,
+ activity = 0,
+ ssid = null,
+ validated = true,
+ )
+
+ assertThat(latest).isEmpty()
+
+ job.cancel()
+ }
+
+ @Test
+ fun `mobile sub updates to carrier merged - only one connection`() =
+ testScope.runTest {
+ var latestSubsList: List<SubscriptionModel>? = null
+ var connections: List<DemoMobileConnectionRepository>? = null
+ val job =
+ underTest.subscriptions
+ .onEach { latestSubsList = it }
+ .onEach { infos ->
+ connections =
+ infos.map { info -> underTest.getRepoForSubId(info.subscriptionId) }
+ }
+ .launchIn(this)
+
+ fakeNetworkEventFlow.value = validMobileEvent(subId = 3, level = 2)
+ assertThat(latestSubsList).hasSize(1)
+
+ val carrierMergedEvent = validCarrierMergedEvent(subId = 3, level = 1)
+ fakeWifiEventFlow.value = carrierMergedEvent
+ assertThat(latestSubsList).hasSize(1)
+ val connection = connections!!.find { it.subId == 3 }!!
+ assertCarrierMergedConnection(connection, carrierMergedEvent)
+
+ job.cancel()
+ }
+
+ @Test
+ fun `mobile sub updates to carrier merged then back - has old mobile data`() =
+ testScope.runTest {
+ var latestSubsList: List<SubscriptionModel>? = null
+ var connections: List<DemoMobileConnectionRepository>? = null
+ val job =
+ underTest.subscriptions
+ .onEach { latestSubsList = it }
+ .onEach { infos ->
+ connections =
+ infos.map { info -> underTest.getRepoForSubId(info.subscriptionId) }
+ }
+ .launchIn(this)
+
+ val mobileEvent = validMobileEvent(subId = 3, level = 2)
+ fakeNetworkEventFlow.value = mobileEvent
+ assertThat(latestSubsList).hasSize(1)
+
+ val carrierMergedEvent = validCarrierMergedEvent(subId = 3, level = 1)
+ fakeWifiEventFlow.value = carrierMergedEvent
+ assertThat(latestSubsList).hasSize(1)
+ var connection = connections!!.find { it.subId == 3 }!!
+ assertCarrierMergedConnection(connection, carrierMergedEvent)
+
+ // WHEN the carrier merged is removed
+ fakeWifiEventFlow.value =
+ FakeWifiEventModel.Wifi(
+ level = 4,
+ activity = 0,
+ ssid = null,
+ validated = true,
+ )
+
+ // THEN the subId=3 connection goes back to the mobile information
+ connection = connections!!.find { it.subId == 3 }!!
+ assertConnection(connection, mobileEvent)
+
+ job.cancel()
+ }
+
/** Regression test for b/261706421 */
@Test
fun `multiple connections - remove all - does not throw`() =
@@ -289,6 +471,51 @@
job.cancel()
}
+ @Test
+ fun `demo connection - two connections - update carrier merged - no affect on first`() =
+ testScope.runTest {
+ var currentEvent1 = validMobileEvent(subId = 1)
+ var connection1: DemoMobileConnectionRepository? = null
+ var currentEvent2 = validCarrierMergedEvent(subId = 2)
+ var connection2: DemoMobileConnectionRepository? = null
+ var connections: List<DemoMobileConnectionRepository>? = null
+ val job =
+ underTest.subscriptions
+ .onEach { infos ->
+ connections =
+ infos.map { info -> underTest.getRepoForSubId(info.subscriptionId) }
+ }
+ .launchIn(this)
+
+ fakeNetworkEventFlow.value = currentEvent1
+ fakeWifiEventFlow.value = currentEvent2
+ assertThat(connections).hasSize(2)
+ connections!!.forEach {
+ when (it.subId) {
+ 1 -> connection1 = it
+ 2 -> connection2 = it
+ else -> Assert.fail("Unexpected subscription")
+ }
+ }
+
+ assertConnection(connection1!!, currentEvent1)
+ assertCarrierMergedConnection(connection2!!, currentEvent2)
+
+ // WHEN the event changes for connection 2, it updates, and connection 1 stays the same
+ currentEvent2 = validCarrierMergedEvent(subId = 2, level = 4)
+ fakeWifiEventFlow.value = currentEvent2
+ assertConnection(connection1!!, currentEvent1)
+ assertCarrierMergedConnection(connection2!!, currentEvent2)
+
+ // and vice versa
+ currentEvent1 = validMobileEvent(subId = 1, inflateStrength = true)
+ fakeNetworkEventFlow.value = currentEvent1
+ assertConnection(connection1!!, currentEvent1)
+ assertCarrierMergedConnection(connection2!!, currentEvent2)
+
+ job.cancel()
+ }
+
private fun assertConnection(
conn: DemoMobileConnectionRepository,
model: FakeNetworkEventModel
@@ -315,6 +542,21 @@
else -> {}
}
}
+
+ private fun assertCarrierMergedConnection(
+ conn: DemoMobileConnectionRepository,
+ model: FakeWifiEventModel.CarrierMerged,
+ ) {
+ val connectionInfo: MobileConnectionModel = conn.connectionInfo.value
+ assertThat(conn.subId).isEqualTo(model.subscriptionId)
+ assertThat(connectionInfo.cdmaLevel).isEqualTo(model.level)
+ assertThat(connectionInfo.primaryLevel).isEqualTo(model.level)
+ assertThat(connectionInfo.carrierNetworkChangeActive).isEqualTo(false)
+ assertThat(connectionInfo.isRoaming).isEqualTo(false)
+ assertThat(connectionInfo.isEmergencyOnly).isFalse()
+ assertThat(connectionInfo.isGsm).isFalse()
+ assertThat(connectionInfo.dataConnectionState).isEqualTo(DataConnectionState.Connected)
+ }
}
/** Convenience to create a valid fake network event with minimal params */
@@ -339,3 +581,14 @@
roaming = roaming,
name = "demo name",
)
+
+fun validCarrierMergedEvent(
+ subId: Int = 1,
+ level: Int = 1,
+ numberOfLevels: Int = 4,
+): FakeWifiEventModel.CarrierMerged =
+ FakeWifiEventModel.CarrierMerged(
+ subscriptionId = subId,
+ level = level,
+ numberOfLevels = numberOfLevels,
+ )
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepositoryTest.kt
new file mode 100644
index 0000000..ea90150
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepositoryTest.kt
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.mobile.data.repository.prod
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
+import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
+import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
+import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType
+import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
+import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel
+import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@OptIn(ExperimentalCoroutinesApi::class)
+@RunWith(AndroidTestingRunner::class)
+class CarrierMergedConnectionRepositoryTest : SysuiTestCase() {
+
+ private lateinit var underTest: CarrierMergedConnectionRepository
+
+ private lateinit var wifiRepository: FakeWifiRepository
+ @Mock private lateinit var logger: TableLogBuffer
+
+ private val testDispatcher = UnconfinedTestDispatcher()
+ private val testScope = TestScope(testDispatcher)
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ wifiRepository = FakeWifiRepository()
+
+ underTest =
+ CarrierMergedConnectionRepository(
+ SUB_ID,
+ logger,
+ NetworkNameModel.Default("name"),
+ testScope.backgroundScope,
+ wifiRepository,
+ )
+ }
+
+ @Test
+ fun connectionInfo_inactiveWifi_isDefault() =
+ testScope.runTest {
+ var latest: MobileConnectionModel? = null
+ val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+
+ wifiRepository.setWifiNetwork(WifiNetworkModel.Inactive)
+
+ assertThat(latest).isEqualTo(MobileConnectionModel())
+
+ job.cancel()
+ }
+
+ @Test
+ fun connectionInfo_activeWifi_isDefault() =
+ testScope.runTest {
+ var latest: MobileConnectionModel? = null
+ val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+
+ wifiRepository.setWifiNetwork(WifiNetworkModel.Active(networkId = NET_ID, level = 1))
+
+ assertThat(latest).isEqualTo(MobileConnectionModel())
+
+ job.cancel()
+ }
+
+ @Test
+ fun connectionInfo_carrierMergedWifi_isValidAndFieldsComeFromWifiNetwork() =
+ testScope.runTest {
+ var latest: MobileConnectionModel? = null
+ val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+
+ wifiRepository.setIsWifiEnabled(true)
+ wifiRepository.setIsWifiDefault(true)
+
+ wifiRepository.setWifiNetwork(
+ WifiNetworkModel.CarrierMerged(
+ networkId = NET_ID,
+ subscriptionId = SUB_ID,
+ level = 3,
+ )
+ )
+
+ val expected =
+ MobileConnectionModel(
+ primaryLevel = 3,
+ cdmaLevel = 3,
+ dataConnectionState = DataConnectionState.Connected,
+ dataActivityDirection =
+ DataActivityModel(
+ hasActivityIn = false,
+ hasActivityOut = false,
+ ),
+ resolvedNetworkType = ResolvedNetworkType.CarrierMergedNetworkType,
+ isRoaming = false,
+ isEmergencyOnly = false,
+ operatorAlphaShort = null,
+ isInService = true,
+ isGsm = false,
+ carrierNetworkChangeActive = false,
+ )
+ assertThat(latest).isEqualTo(expected)
+
+ job.cancel()
+ }
+
+ @Test
+ fun connectionInfo_carrierMergedWifi_wrongSubId_isDefault() =
+ testScope.runTest {
+ var latest: MobileConnectionModel? = null
+ val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+
+ wifiRepository.setWifiNetwork(
+ WifiNetworkModel.CarrierMerged(
+ networkId = NET_ID,
+ subscriptionId = SUB_ID + 10,
+ level = 3,
+ )
+ )
+
+ assertThat(latest).isEqualTo(MobileConnectionModel())
+ assertThat(latest!!.primaryLevel).isNotEqualTo(3)
+ assertThat(latest!!.resolvedNetworkType)
+ .isNotEqualTo(ResolvedNetworkType.CarrierMergedNetworkType)
+
+ job.cancel()
+ }
+
+ // This scenario likely isn't possible, but write a test for it anyway
+ @Test
+ fun connectionInfo_carrierMergedButNotEnabled_isDefault() =
+ testScope.runTest {
+ var latest: MobileConnectionModel? = null
+ val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+
+ wifiRepository.setWifiNetwork(
+ WifiNetworkModel.CarrierMerged(
+ networkId = NET_ID,
+ subscriptionId = SUB_ID,
+ level = 3,
+ )
+ )
+ wifiRepository.setIsWifiEnabled(false)
+
+ assertThat(latest).isEqualTo(MobileConnectionModel())
+
+ job.cancel()
+ }
+
+ // This scenario likely isn't possible, but write a test for it anyway
+ @Test
+ fun connectionInfo_carrierMergedButWifiNotDefault_isDefault() =
+ testScope.runTest {
+ var latest: MobileConnectionModel? = null
+ val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+
+ wifiRepository.setWifiNetwork(
+ WifiNetworkModel.CarrierMerged(
+ networkId = NET_ID,
+ subscriptionId = SUB_ID,
+ level = 3,
+ )
+ )
+ wifiRepository.setIsWifiDefault(false)
+
+ assertThat(latest).isEqualTo(MobileConnectionModel())
+
+ job.cancel()
+ }
+
+ @Test
+ fun numberOfLevels_comesFromCarrierMerged() =
+ testScope.runTest {
+ var latest: Int? = null
+ val job = underTest.numberOfLevels.onEach { latest = it }.launchIn(this)
+
+ wifiRepository.setWifiNetwork(
+ WifiNetworkModel.CarrierMerged(
+ networkId = NET_ID,
+ subscriptionId = SUB_ID,
+ level = 1,
+ numberOfLevels = 6,
+ )
+ )
+
+ assertThat(latest).isEqualTo(6)
+
+ job.cancel()
+ }
+
+ @Test
+ fun dataEnabled_matchesWifiEnabled() =
+ testScope.runTest {
+ var latest: Boolean? = null
+ val job = underTest.dataEnabled.onEach { latest = it }.launchIn(this)
+
+ wifiRepository.setIsWifiEnabled(true)
+ assertThat(latest).isTrue()
+
+ wifiRepository.setIsWifiEnabled(false)
+ assertThat(latest).isFalse()
+
+ job.cancel()
+ }
+
+ @Test
+ fun cdmaRoaming_alwaysFalse() =
+ testScope.runTest {
+ var latest: Boolean? = null
+ val job = underTest.cdmaRoaming.onEach { latest = it }.launchIn(this)
+
+ assertThat(latest).isFalse()
+
+ job.cancel()
+ }
+
+ private companion object {
+ const val SUB_ID = 123
+ const val NET_ID = 456
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt
new file mode 100644
index 0000000..c02a4df
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt
@@ -0,0 +1,389 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.mobile.data.repository.prod
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.log.table.TableLogBufferFactory
+import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
+import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionRepository
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
+import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.util.time.FakeSystemClock
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+
+/**
+ * This repo acts as a dispatcher to either the `typical` or `carrier merged` versions of the
+ * repository interface it's switching on. These tests just need to verify that the entire interface
+ * properly switches over when the value of `isCarrierMerged` changes.
+ */
+@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+class FullMobileConnectionRepositoryTest : SysuiTestCase() {
+ private lateinit var underTest: FullMobileConnectionRepository
+
+ private val testDispatcher = UnconfinedTestDispatcher()
+ private val testScope = TestScope(testDispatcher)
+ private val mobileMappings = FakeMobileMappingsProxy()
+ private val tableLogBuffer = mock<TableLogBuffer>()
+ private val mobileFactory = mock<MobileConnectionRepositoryImpl.Factory>()
+ private val carrierMergedFactory = mock<CarrierMergedConnectionRepository.Factory>()
+
+ private lateinit var connectionsRepo: FakeMobileConnectionsRepository
+ private val globalMobileDataSettingChangedEvent: Flow<Unit>
+ get() = connectionsRepo.globalMobileDataSettingChangedEvent
+
+ private lateinit var mobileRepo: FakeMobileConnectionRepository
+ private lateinit var carrierMergedRepo: FakeMobileConnectionRepository
+
+ @Before
+ fun setUp() {
+ connectionsRepo = FakeMobileConnectionsRepository(mobileMappings, tableLogBuffer)
+
+ mobileRepo = FakeMobileConnectionRepository(SUB_ID, tableLogBuffer)
+ carrierMergedRepo = FakeMobileConnectionRepository(SUB_ID, tableLogBuffer)
+
+ whenever(
+ mobileFactory.build(
+ eq(SUB_ID),
+ any(),
+ eq(DEFAULT_NAME),
+ eq(SEP),
+ eq(globalMobileDataSettingChangedEvent),
+ )
+ )
+ .thenReturn(mobileRepo)
+ whenever(carrierMergedFactory.build(eq(SUB_ID), any(), eq(DEFAULT_NAME)))
+ .thenReturn(carrierMergedRepo)
+ }
+
+ @Test
+ fun startingIsCarrierMerged_usesCarrierMergedInitially() =
+ testScope.runTest {
+ val carrierMergedConnectionInfo =
+ MobileConnectionModel(
+ operatorAlphaShort = "Carrier Merged Operator",
+ )
+ carrierMergedRepo.setConnectionInfo(carrierMergedConnectionInfo)
+
+ initializeRepo(startingIsCarrierMerged = true)
+
+ assertThat(underTest.activeRepo.value).isEqualTo(carrierMergedRepo)
+ assertThat(underTest.connectionInfo.value).isEqualTo(carrierMergedConnectionInfo)
+ verify(mobileFactory, never())
+ .build(
+ SUB_ID,
+ tableLogBuffer,
+ DEFAULT_NAME,
+ SEP,
+ globalMobileDataSettingChangedEvent
+ )
+ }
+
+ @Test
+ fun startingNotCarrierMerged_usesTypicalInitially() =
+ testScope.runTest {
+ val mobileConnectionInfo =
+ MobileConnectionModel(
+ operatorAlphaShort = "Typical Operator",
+ )
+ mobileRepo.setConnectionInfo(mobileConnectionInfo)
+
+ initializeRepo(startingIsCarrierMerged = false)
+
+ assertThat(underTest.activeRepo.value).isEqualTo(mobileRepo)
+ assertThat(underTest.connectionInfo.value).isEqualTo(mobileConnectionInfo)
+ verify(carrierMergedFactory, never()).build(SUB_ID, tableLogBuffer, DEFAULT_NAME)
+ }
+
+ @Test
+ fun activeRepo_matchesIsCarrierMerged() =
+ testScope.runTest {
+ initializeRepo(startingIsCarrierMerged = false)
+ var latest: MobileConnectionRepository? = null
+ val job = underTest.activeRepo.onEach { latest = it }.launchIn(this)
+
+ underTest.setIsCarrierMerged(true)
+
+ assertThat(latest).isEqualTo(carrierMergedRepo)
+
+ underTest.setIsCarrierMerged(false)
+
+ assertThat(latest).isEqualTo(mobileRepo)
+
+ underTest.setIsCarrierMerged(true)
+
+ assertThat(latest).isEqualTo(carrierMergedRepo)
+
+ job.cancel()
+ }
+
+ @Test
+ fun connectionInfo_getsUpdatesFromRepo_carrierMerged() =
+ testScope.runTest {
+ initializeRepo(startingIsCarrierMerged = false)
+
+ var latest: MobileConnectionModel? = null
+ val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+
+ underTest.setIsCarrierMerged(true)
+
+ val info1 =
+ MobileConnectionModel(
+ operatorAlphaShort = "Carrier Merged Operator",
+ primaryLevel = 1,
+ )
+ carrierMergedRepo.setConnectionInfo(info1)
+
+ assertThat(latest).isEqualTo(info1)
+
+ val info2 =
+ MobileConnectionModel(
+ operatorAlphaShort = "Carrier Merged Operator #2",
+ primaryLevel = 2,
+ )
+ carrierMergedRepo.setConnectionInfo(info2)
+
+ assertThat(latest).isEqualTo(info2)
+
+ val info3 =
+ MobileConnectionModel(
+ operatorAlphaShort = "Carrier Merged Operator #3",
+ primaryLevel = 3,
+ )
+ carrierMergedRepo.setConnectionInfo(info3)
+
+ assertThat(latest).isEqualTo(info3)
+
+ job.cancel()
+ }
+
+ @Test
+ fun connectionInfo_getsUpdatesFromRepo_mobile() =
+ testScope.runTest {
+ initializeRepo(startingIsCarrierMerged = false)
+
+ var latest: MobileConnectionModel? = null
+ val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+
+ underTest.setIsCarrierMerged(false)
+
+ val info1 =
+ MobileConnectionModel(
+ operatorAlphaShort = "Typical Merged Operator",
+ primaryLevel = 1,
+ )
+ mobileRepo.setConnectionInfo(info1)
+
+ assertThat(latest).isEqualTo(info1)
+
+ val info2 =
+ MobileConnectionModel(
+ operatorAlphaShort = "Typical Merged Operator #2",
+ primaryLevel = 2,
+ )
+ mobileRepo.setConnectionInfo(info2)
+
+ assertThat(latest).isEqualTo(info2)
+
+ val info3 =
+ MobileConnectionModel(
+ operatorAlphaShort = "Typical Merged Operator #3",
+ primaryLevel = 3,
+ )
+ mobileRepo.setConnectionInfo(info3)
+
+ assertThat(latest).isEqualTo(info3)
+
+ job.cancel()
+ }
+
+ @Test
+ fun connectionInfo_updatesWhenCarrierMergedUpdates() =
+ testScope.runTest {
+ initializeRepo(startingIsCarrierMerged = false)
+
+ var latest: MobileConnectionModel? = null
+ val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+
+ val carrierMergedInfo =
+ MobileConnectionModel(
+ operatorAlphaShort = "Carrier Merged Operator",
+ primaryLevel = 4,
+ )
+ carrierMergedRepo.setConnectionInfo(carrierMergedInfo)
+
+ val mobileInfo =
+ MobileConnectionModel(
+ operatorAlphaShort = "Typical Operator",
+ primaryLevel = 2,
+ )
+ mobileRepo.setConnectionInfo(mobileInfo)
+
+ // Start with the mobile info
+ assertThat(latest).isEqualTo(mobileInfo)
+
+ // WHEN isCarrierMerged is set to true
+ underTest.setIsCarrierMerged(true)
+
+ // THEN the carrier merged info is used
+ assertThat(latest).isEqualTo(carrierMergedInfo)
+
+ val newCarrierMergedInfo =
+ MobileConnectionModel(
+ operatorAlphaShort = "New CM Operator",
+ primaryLevel = 0,
+ )
+ carrierMergedRepo.setConnectionInfo(newCarrierMergedInfo)
+
+ assertThat(latest).isEqualTo(newCarrierMergedInfo)
+
+ // WHEN isCarrierMerged is set to false
+ underTest.setIsCarrierMerged(false)
+
+ // THEN the typical info is used
+ assertThat(latest).isEqualTo(mobileInfo)
+
+ val newMobileInfo =
+ MobileConnectionModel(
+ operatorAlphaShort = "New Mobile Operator",
+ primaryLevel = 3,
+ )
+ mobileRepo.setConnectionInfo(newMobileInfo)
+
+ assertThat(latest).isEqualTo(newMobileInfo)
+
+ job.cancel()
+ }
+
+ @Test
+ fun `factory - reuses log buffers for same connection`() =
+ testScope.runTest {
+ val realLoggerFactory = TableLogBufferFactory(mock(), FakeSystemClock())
+
+ val factory =
+ FullMobileConnectionRepository.Factory(
+ scope = testScope.backgroundScope,
+ realLoggerFactory,
+ mobileFactory,
+ carrierMergedFactory,
+ )
+
+ // Create two connections for the same subId. Similar to if the connection appeared
+ // and disappeared from the connectionFactory's perspective
+ val connection1 =
+ factory.build(
+ SUB_ID,
+ startingIsCarrierMerged = false,
+ DEFAULT_NAME,
+ SEP,
+ globalMobileDataSettingChangedEvent,
+ )
+
+ val connection1Repeat =
+ factory.build(
+ SUB_ID,
+ startingIsCarrierMerged = false,
+ DEFAULT_NAME,
+ SEP,
+ globalMobileDataSettingChangedEvent,
+ )
+
+ assertThat(connection1.tableLogBuffer)
+ .isSameInstanceAs(connection1Repeat.tableLogBuffer)
+ }
+
+ @Test
+ fun `factory - reuses log buffers for same sub ID even if carrier merged`() =
+ testScope.runTest {
+ val realLoggerFactory = TableLogBufferFactory(mock(), FakeSystemClock())
+
+ val factory =
+ FullMobileConnectionRepository.Factory(
+ scope = testScope.backgroundScope,
+ realLoggerFactory,
+ mobileFactory,
+ carrierMergedFactory,
+ )
+
+ val connection1 =
+ factory.build(
+ SUB_ID,
+ startingIsCarrierMerged = false,
+ DEFAULT_NAME,
+ SEP,
+ globalMobileDataSettingChangedEvent,
+ )
+
+ // WHEN a connection with the same sub ID but carrierMerged = true is created
+ val connection1Repeat =
+ factory.build(
+ SUB_ID,
+ startingIsCarrierMerged = true,
+ DEFAULT_NAME,
+ SEP,
+ globalMobileDataSettingChangedEvent,
+ )
+
+ // THEN the same table is re-used
+ assertThat(connection1.tableLogBuffer)
+ .isSameInstanceAs(connection1Repeat.tableLogBuffer)
+ }
+
+ // TODO(b/238425913): Verify that the logging switches correctly (once the carrier merged repo
+ // implements logging).
+
+ private fun initializeRepo(startingIsCarrierMerged: Boolean) {
+ underTest =
+ FullMobileConnectionRepository(
+ SUB_ID,
+ startingIsCarrierMerged,
+ tableLogBuffer,
+ DEFAULT_NAME,
+ SEP,
+ globalMobileDataSettingChangedEvent,
+ testScope.backgroundScope,
+ mobileFactory,
+ carrierMergedFactory,
+ )
+ }
+
+ private companion object {
+ const val SUB_ID = 42
+ private val DEFAULT_NAME = NetworkNameModel.Default("default name")
+ private const val SEP = "-"
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt
index 0da15e2..813b0ed 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt
@@ -38,8 +38,11 @@
import com.android.systemui.log.table.TableLogBufferFactory
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectivityModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Factory.Companion.tableBufferLogName
import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
+import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel
+import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.eq
@@ -72,6 +75,9 @@
private lateinit var underTest: MobileConnectionsRepositoryImpl
private lateinit var connectionFactory: MobileConnectionRepositoryImpl.Factory
+ private lateinit var carrierMergedFactory: CarrierMergedConnectionRepository.Factory
+ private lateinit var fullConnectionFactory: FullMobileConnectionRepository.Factory
+ private lateinit var wifiRepository: FakeWifiRepository
@Mock private lateinit var connectivityManager: ConnectivityManager
@Mock private lateinit var subscriptionManager: SubscriptionManager
@Mock private lateinit var telephonyManager: TelephonyManager
@@ -94,10 +100,12 @@
}
}
- whenever(logBufferFactory.create(anyString(), anyInt())).thenAnswer { _ ->
+ whenever(logBufferFactory.getOrCreate(anyString(), anyInt())).thenAnswer { _ ->
mock<TableLogBuffer>()
}
+ wifiRepository = FakeWifiRepository()
+
connectionFactory =
MobileConnectionRepositoryImpl.Factory(
fakeBroadcastDispatcher,
@@ -108,7 +116,18 @@
logger = logger,
mobileMappingsProxy = mobileMappings,
scope = scope,
+ )
+ carrierMergedFactory =
+ CarrierMergedConnectionRepository.Factory(
+ scope,
+ wifiRepository,
+ )
+ fullConnectionFactory =
+ FullMobileConnectionRepository.Factory(
+ scope = scope,
logFactory = logBufferFactory,
+ mobileRepoFactory = connectionFactory,
+ carrierMergedRepoFactory = carrierMergedFactory,
)
underTest =
@@ -123,7 +142,8 @@
context,
IMMEDIATE,
scope,
- connectionFactory,
+ wifiRepository,
+ fullConnectionFactory,
)
}
@@ -178,6 +198,40 @@
}
@Test
+ fun testSubscriptions_carrierMergedOnly_listHasCarrierMerged() =
+ runBlocking(IMMEDIATE) {
+ var latest: List<SubscriptionModel>? = null
+
+ val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
+
+ wifiRepository.setWifiNetwork(WIFI_NETWORK_CM)
+ whenever(subscriptionManager.completeActiveSubscriptionInfoList)
+ .thenReturn(listOf(SUB_CM))
+ getSubscriptionCallback().onSubscriptionsChanged()
+
+ assertThat(latest).isEqualTo(listOf(MODEL_CM))
+
+ job.cancel()
+ }
+
+ @Test
+ fun testSubscriptions_carrierMergedAndOther_listHasBothWithCarrierMergedLast() =
+ runBlocking(IMMEDIATE) {
+ var latest: List<SubscriptionModel>? = null
+
+ val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
+
+ wifiRepository.setWifiNetwork(WIFI_NETWORK_CM)
+ whenever(subscriptionManager.completeActiveSubscriptionInfoList)
+ .thenReturn(listOf(SUB_1, SUB_2, SUB_CM))
+ getSubscriptionCallback().onSubscriptionsChanged()
+
+ assertThat(latest).isEqualTo(listOf(MODEL_1, MODEL_2, MODEL_CM))
+
+ job.cancel()
+ }
+
+ @Test
fun testActiveDataSubscriptionId_initialValueIsInvalidId() =
runBlocking(IMMEDIATE) {
assertThat(underTest.activeMobileDataSubscriptionId.value)
@@ -217,6 +271,96 @@
}
@Test
+ fun testConnectionRepository_carrierMergedSubId_isCached() =
+ runBlocking(IMMEDIATE) {
+ val job = underTest.subscriptions.launchIn(this)
+
+ wifiRepository.setWifiNetwork(WIFI_NETWORK_CM)
+ whenever(subscriptionManager.completeActiveSubscriptionInfoList)
+ .thenReturn(listOf(SUB_CM))
+ getSubscriptionCallback().onSubscriptionsChanged()
+
+ val repo1 = underTest.getRepoForSubId(SUB_CM_ID)
+ val repo2 = underTest.getRepoForSubId(SUB_CM_ID)
+
+ assertThat(repo1).isSameInstanceAs(repo2)
+
+ job.cancel()
+ }
+
+ @Test
+ fun testConnectionRepository_carrierMergedAndMobileSubs_usesCorrectRepos() =
+ runBlocking(IMMEDIATE) {
+ val job = underTest.subscriptions.launchIn(this)
+
+ wifiRepository.setWifiNetwork(WIFI_NETWORK_CM)
+ whenever(subscriptionManager.completeActiveSubscriptionInfoList)
+ .thenReturn(listOf(SUB_1, SUB_CM))
+ getSubscriptionCallback().onSubscriptionsChanged()
+
+ val carrierMergedRepo = underTest.getRepoForSubId(SUB_CM_ID)
+ val mobileRepo = underTest.getRepoForSubId(SUB_1_ID)
+ assertThat(carrierMergedRepo.getIsCarrierMerged()).isTrue()
+ assertThat(mobileRepo.getIsCarrierMerged()).isFalse()
+
+ job.cancel()
+ }
+
+ @Test
+ fun testSubscriptions_subNoLongerCarrierMerged_repoUpdates() =
+ runBlocking(IMMEDIATE) {
+ val job = underTest.subscriptions.launchIn(this)
+
+ wifiRepository.setWifiNetwork(WIFI_NETWORK_CM)
+ whenever(subscriptionManager.completeActiveSubscriptionInfoList)
+ .thenReturn(listOf(SUB_1, SUB_CM))
+ getSubscriptionCallback().onSubscriptionsChanged()
+
+ val carrierMergedRepo = underTest.getRepoForSubId(SUB_CM_ID)
+ var mobileRepo = underTest.getRepoForSubId(SUB_1_ID)
+ assertThat(carrierMergedRepo.getIsCarrierMerged()).isTrue()
+ assertThat(mobileRepo.getIsCarrierMerged()).isFalse()
+
+ // WHEN the wifi network updates to be not carrier merged
+ wifiRepository.setWifiNetwork(WifiNetworkModel.Active(networkId = 4, level = 1))
+
+ // THEN the repos update
+ val noLongerCarrierMergedRepo = underTest.getRepoForSubId(SUB_CM_ID)
+ mobileRepo = underTest.getRepoForSubId(SUB_1_ID)
+ assertThat(noLongerCarrierMergedRepo.getIsCarrierMerged()).isFalse()
+ assertThat(mobileRepo.getIsCarrierMerged()).isFalse()
+
+ job.cancel()
+ }
+
+ @Test
+ fun testSubscriptions_subBecomesCarrierMerged_repoUpdates() =
+ runBlocking(IMMEDIATE) {
+ val job = underTest.subscriptions.launchIn(this)
+
+ wifiRepository.setWifiNetwork(WifiNetworkModel.Inactive)
+ whenever(subscriptionManager.completeActiveSubscriptionInfoList)
+ .thenReturn(listOf(SUB_1, SUB_CM))
+ getSubscriptionCallback().onSubscriptionsChanged()
+
+ val notYetCarrierMergedRepo = underTest.getRepoForSubId(SUB_CM_ID)
+ var mobileRepo = underTest.getRepoForSubId(SUB_1_ID)
+ assertThat(notYetCarrierMergedRepo.getIsCarrierMerged()).isFalse()
+ assertThat(mobileRepo.getIsCarrierMerged()).isFalse()
+
+ // WHEN the wifi network updates to be carrier merged
+ wifiRepository.setWifiNetwork(WIFI_NETWORK_CM)
+
+ // THEN the repos update
+ val carrierMergedRepo = underTest.getRepoForSubId(SUB_CM_ID)
+ mobileRepo = underTest.getRepoForSubId(SUB_1_ID)
+ assertThat(carrierMergedRepo.getIsCarrierMerged()).isTrue()
+ assertThat(mobileRepo.getIsCarrierMerged()).isFalse()
+
+ job.cancel()
+ }
+
+ @Test
fun testConnectionCache_clearsInvalidSubscriptions() =
runBlocking(IMMEDIATE) {
val job = underTest.subscriptions.launchIn(this)
@@ -242,6 +386,34 @@
job.cancel()
}
+ @Test
+ fun testConnectionCache_clearsInvalidSubscriptions_includingCarrierMerged() =
+ runBlocking(IMMEDIATE) {
+ val job = underTest.subscriptions.launchIn(this)
+
+ wifiRepository.setWifiNetwork(WIFI_NETWORK_CM)
+ whenever(subscriptionManager.completeActiveSubscriptionInfoList)
+ .thenReturn(listOf(SUB_1, SUB_2, SUB_CM))
+ getSubscriptionCallback().onSubscriptionsChanged()
+
+ // Get repos to trigger caching
+ val repo1 = underTest.getRepoForSubId(SUB_1_ID)
+ val repo2 = underTest.getRepoForSubId(SUB_2_ID)
+ val repoCarrierMerged = underTest.getRepoForSubId(SUB_CM_ID)
+
+ assertThat(underTest.getSubIdRepoCache())
+ .containsExactly(SUB_1_ID, repo1, SUB_2_ID, repo2, SUB_CM_ID, repoCarrierMerged)
+
+ // SUB_2 and SUB_CM disappear
+ whenever(subscriptionManager.completeActiveSubscriptionInfoList)
+ .thenReturn(listOf(SUB_1))
+ getSubscriptionCallback().onSubscriptionsChanged()
+
+ assertThat(underTest.getSubIdRepoCache()).containsExactly(SUB_1_ID, repo1)
+
+ job.cancel()
+ }
+
/** Regression test for b/261706421 */
@Test
fun testConnectionsCache_clearMultipleSubscriptionsAtOnce_doesNotThrow() =
@@ -292,14 +464,14 @@
// Get repos to trigger creation
underTest.getRepoForSubId(SUB_1_ID)
verify(logBufferFactory)
- .create(
- eq(MobileConnectionRepositoryImpl.tableBufferLogName(SUB_1_ID)),
+ .getOrCreate(
+ eq(tableBufferLogName(SUB_1_ID)),
anyInt(),
)
underTest.getRepoForSubId(SUB_2_ID)
verify(logBufferFactory)
- .create(
- eq(MobileConnectionRepositoryImpl.tableBufferLogName(SUB_2_ID)),
+ .getOrCreate(
+ eq(tableBufferLogName(SUB_2_ID)),
anyInt(),
)
@@ -419,7 +591,8 @@
context,
IMMEDIATE,
scope,
- connectionFactory,
+ wifiRepository,
+ fullConnectionFactory,
)
var latest: MobileMappings.Config? = null
@@ -529,5 +702,16 @@
private const val NET_ID = 123
private val NETWORK = mock<Network>().apply { whenever(getNetId()).thenReturn(NET_ID) }
+
+ private const val SUB_CM_ID = 5
+ private val SUB_CM =
+ mock<SubscriptionInfo>().also { whenever(it.subscriptionId).thenReturn(SUB_CM_ID) }
+ private val MODEL_CM = SubscriptionModel(subscriptionId = SUB_CM_ID)
+ private val WIFI_NETWORK_CM =
+ WifiNetworkModel.CarrierMerged(
+ networkId = 3,
+ subscriptionId = SUB_CM_ID,
+ level = 1,
+ )
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt
index 61e13b8..e6be7f1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt
@@ -25,6 +25,7 @@
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
+import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.CarrierMergedNetworkType
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.DefaultNetworkType
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.OverrideNetworkType
import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionRepository
@@ -271,6 +272,23 @@
}
@Test
+ fun iconGroup_carrierMerged_usesOverride() =
+ runBlocking(IMMEDIATE) {
+ connectionRepository.setConnectionInfo(
+ MobileConnectionModel(
+ resolvedNetworkType = CarrierMergedNetworkType,
+ ),
+ )
+
+ var latest: MobileIconGroup? = null
+ val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this)
+
+ assertThat(latest).isEqualTo(CarrierMergedNetworkType.iconGroupOverride)
+
+ job.cancel()
+ }
+
+ @Test
fun alwaysShowDataRatIcon_matchesParent() =
runBlocking(IMMEDIATE) {
var latest: Boolean? = null
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/model/WifiNetworkModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/model/WifiNetworkModelTest.kt
index 30ac8d4..824cebd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/model/WifiNetworkModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/model/WifiNetworkModelTest.kt
@@ -16,11 +16,12 @@
package com.android.systemui.statusbar.pipeline.wifi.data.model
+import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.log.table.TableRowLogger
import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel.Active.Companion.MAX_VALID_LEVEL
-import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel.Active.Companion.MIN_VALID_LEVEL
+import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel.Companion.MIN_VALID_LEVEL
import com.google.common.truth.Truth.assertThat
import org.junit.Test
@@ -44,9 +45,53 @@
WifiNetworkModel.Active(NETWORK_ID, level = MAX_VALID_LEVEL + 1)
}
+ @Test(expected = IllegalArgumentException::class)
+ fun carrierMerged_invalidSubId_exceptionThrown() {
+ WifiNetworkModel.CarrierMerged(NETWORK_ID, INVALID_SUBSCRIPTION_ID, 1)
+ }
+
// Non-exhaustive logDiffs test -- just want to make sure the logging logic isn't totally broken
@Test
+ fun logDiffs_carrierMergedToInactive_resetsAllFields() {
+ val logger = TestLogger()
+ val prevVal =
+ WifiNetworkModel.CarrierMerged(
+ networkId = 5,
+ subscriptionId = 3,
+ level = 1,
+ )
+
+ WifiNetworkModel.Inactive.logDiffs(prevVal, logger)
+
+ assertThat(logger.changes).contains(Pair(COL_NETWORK_TYPE, TYPE_INACTIVE))
+ assertThat(logger.changes).contains(Pair(COL_NETWORK_ID, NETWORK_ID_DEFAULT.toString()))
+ assertThat(logger.changes).contains(Pair(COL_VALIDATED, "false"))
+ assertThat(logger.changes).contains(Pair(COL_LEVEL, LEVEL_DEFAULT.toString()))
+ assertThat(logger.changes).contains(Pair(COL_SSID, "null"))
+ }
+
+ @Test
+ fun logDiffs_inactiveToCarrierMerged_logsAllFields() {
+ val logger = TestLogger()
+ val carrierMerged =
+ WifiNetworkModel.CarrierMerged(
+ networkId = 6,
+ subscriptionId = 3,
+ level = 2,
+ )
+
+ carrierMerged.logDiffs(prevVal = WifiNetworkModel.Inactive, logger)
+
+ assertThat(logger.changes).contains(Pair(COL_NETWORK_TYPE, TYPE_CARRIER_MERGED))
+ assertThat(logger.changes).contains(Pair(COL_NETWORK_ID, "6"))
+ assertThat(logger.changes).contains(Pair(COL_SUB_ID, "3"))
+ assertThat(logger.changes).contains(Pair(COL_VALIDATED, "true"))
+ assertThat(logger.changes).contains(Pair(COL_LEVEL, "2"))
+ assertThat(logger.changes).contains(Pair(COL_SSID, "null"))
+ }
+
+ @Test
fun logDiffs_inactiveToActive_logsAllActiveFields() {
val logger = TestLogger()
val activeNetwork =
@@ -95,8 +140,14 @@
level = 3,
ssid = "Test SSID"
)
+ val prevVal =
+ WifiNetworkModel.CarrierMerged(
+ networkId = 5,
+ subscriptionId = 3,
+ level = 1,
+ )
- activeNetwork.logDiffs(prevVal = WifiNetworkModel.CarrierMerged, logger)
+ activeNetwork.logDiffs(prevVal, logger)
assertThat(logger.changes).contains(Pair(COL_NETWORK_TYPE, TYPE_ACTIVE))
assertThat(logger.changes).contains(Pair(COL_NETWORK_ID, "5"))
@@ -105,7 +156,7 @@
assertThat(logger.changes).contains(Pair(COL_SSID, "Test SSID"))
}
@Test
- fun logDiffs_activeToCarrierMerged_resetsAllActiveFields() {
+ fun logDiffs_activeToCarrierMerged_logsAllFields() {
val logger = TestLogger()
val activeNetwork =
WifiNetworkModel.Active(
@@ -114,13 +165,20 @@
level = 3,
ssid = "Test SSID"
)
+ val carrierMerged =
+ WifiNetworkModel.CarrierMerged(
+ networkId = 6,
+ subscriptionId = 3,
+ level = 2,
+ )
- WifiNetworkModel.CarrierMerged.logDiffs(prevVal = activeNetwork, logger)
+ carrierMerged.logDiffs(prevVal = activeNetwork, logger)
assertThat(logger.changes).contains(Pair(COL_NETWORK_TYPE, TYPE_CARRIER_MERGED))
- assertThat(logger.changes).contains(Pair(COL_NETWORK_ID, NETWORK_ID_DEFAULT.toString()))
- assertThat(logger.changes).contains(Pair(COL_VALIDATED, "false"))
- assertThat(logger.changes).contains(Pair(COL_LEVEL, LEVEL_DEFAULT.toString()))
+ assertThat(logger.changes).contains(Pair(COL_NETWORK_ID, "6"))
+ assertThat(logger.changes).contains(Pair(COL_SUB_ID, "3"))
+ assertThat(logger.changes).contains(Pair(COL_VALIDATED, "true"))
+ assertThat(logger.changes).contains(Pair(COL_LEVEL, "2"))
assertThat(logger.changes).contains(Pair(COL_SSID, "null"))
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt
index 8f07615..87ce8fa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt
@@ -26,6 +26,7 @@
import android.net.wifi.WifiInfo
import android.net.wifi.WifiManager
import android.net.wifi.WifiManager.TrafficStateCallback
+import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.broadcast.BroadcastDispatcher
@@ -340,7 +341,6 @@
.launchIn(this)
val wifiInfo = mock<WifiInfo>().apply {
- whenever(this.ssid).thenReturn(SSID)
whenever(this.isPrimary).thenReturn(true)
whenever(this.isCarrierMerged).thenReturn(true)
}
@@ -353,6 +353,67 @@
}
@Test
+ fun wifiNetwork_carrierMergedButInvalidSubId_flowHasInvalid() =
+ runBlocking(IMMEDIATE) {
+ var latest: WifiNetworkModel? = null
+ val job = underTest
+ .wifiNetwork
+ .onEach { latest = it }
+ .launchIn(this)
+
+ val wifiInfo = mock<WifiInfo>().apply {
+ whenever(this.isPrimary).thenReturn(true)
+ whenever(this.isCarrierMerged).thenReturn(true)
+ whenever(this.subscriptionId).thenReturn(INVALID_SUBSCRIPTION_ID)
+ }
+
+ getNetworkCallback().onCapabilitiesChanged(
+ NETWORK,
+ createWifiNetworkCapabilities(wifiInfo),
+ )
+
+ assertThat(latest).isInstanceOf(WifiNetworkModel.Invalid::class.java)
+
+ job.cancel()
+ }
+
+ @Test
+ fun wifiNetwork_isCarrierMerged_getsCorrectValues() =
+ runBlocking(IMMEDIATE) {
+ var latest: WifiNetworkModel? = null
+ val job = underTest
+ .wifiNetwork
+ .onEach { latest = it }
+ .launchIn(this)
+
+ val rssi = -57
+ val wifiInfo = mock<WifiInfo>().apply {
+ whenever(this.isPrimary).thenReturn(true)
+ whenever(this.isCarrierMerged).thenReturn(true)
+ whenever(this.rssi).thenReturn(rssi)
+ whenever(this.subscriptionId).thenReturn(567)
+ }
+
+ whenever(wifiManager.calculateSignalLevel(rssi)).thenReturn(2)
+ whenever(wifiManager.maxSignalLevel).thenReturn(5)
+
+ getNetworkCallback().onCapabilitiesChanged(
+ NETWORK,
+ createWifiNetworkCapabilities(wifiInfo),
+ )
+
+ assertThat(latest is WifiNetworkModel.CarrierMerged).isTrue()
+ val latestCarrierMerged = latest as WifiNetworkModel.CarrierMerged
+ assertThat(latestCarrierMerged.networkId).isEqualTo(NETWORK_ID)
+ assertThat(latestCarrierMerged.subscriptionId).isEqualTo(567)
+ assertThat(latestCarrierMerged.level).isEqualTo(2)
+ // numberOfLevels = maxSignalLevel + 1
+ assertThat(latestCarrierMerged.numberOfLevels).isEqualTo(6)
+
+ job.cancel()
+ }
+
+ @Test
fun wifiNetwork_notValidated_networkNotValidated() = runBlocking(IMMEDIATE) {
var latest: WifiNetworkModel? = null
val job = underTest
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorImplTest.kt
index 01d59f9..089a170 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorImplTest.kt
@@ -84,7 +84,9 @@
@Test
fun ssid_carrierMergedNetwork_outputsNull() = runBlocking(IMMEDIATE) {
- wifiRepository.setWifiNetwork(WifiNetworkModel.CarrierMerged)
+ wifiRepository.setWifiNetwork(
+ WifiNetworkModel.CarrierMerged(networkId = 1, subscriptionId = 2, level = 1)
+ )
var latest: String? = "default"
val job = underTest
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt
index 726e813..b932837 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt
@@ -206,7 +206,8 @@
// Enabled = false => no networks shown
TestCase(
enabled = false,
- network = WifiNetworkModel.CarrierMerged,
+ network =
+ WifiNetworkModel.CarrierMerged(NETWORK_ID, subscriptionId = 1, level = 1),
expected = null,
),
TestCase(
@@ -228,7 +229,8 @@
// forceHidden = true => no networks shown
TestCase(
forceHidden = true,
- network = WifiNetworkModel.CarrierMerged,
+ network =
+ WifiNetworkModel.CarrierMerged(NETWORK_ID, subscriptionId = 1, level = 1),
expected = null,
),
TestCase(
@@ -369,7 +371,8 @@
// network = CarrierMerged => not shown
TestCase(
- network = WifiNetworkModel.CarrierMerged,
+ network =
+ WifiNetworkModel.CarrierMerged(NETWORK_ID, subscriptionId = 1, level = 1),
expected = null,
),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java
index 4b32ee2..0cca7b2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java
@@ -390,19 +390,27 @@
bindController(view, row.getEntry());
view.setVisibility(View.GONE);
- View crossFadeView = new View(mContext);
+ View fadeOutView = new View(mContext);
+ fadeOutView.setId(com.android.internal.R.id.actions_container_layout);
+
+ FrameLayout parent = new FrameLayout(mContext);
+ parent.addView(view);
+ parent.addView(fadeOutView);
// Start focus animation
- view.focusAnimated(crossFadeView);
-
+ view.focusAnimated();
assertTrue(view.isAnimatingAppearance());
- // fast forward to end of animation
- mAnimatorTestRule.advanceTimeBy(ANIMATION_DURATION_STANDARD);
+ // fast forward to 1 ms before end of animation and verify fadeOutView has alpha set to 0f
+ mAnimatorTestRule.advanceTimeBy(ANIMATION_DURATION_STANDARD - 1);
+ assertEquals(0f, fadeOutView.getAlpha());
- // assert that crossFadeView's alpha is reset to 1f after the animation (hidden behind
+ // fast forward to end of animation
+ mAnimatorTestRule.advanceTimeBy(1);
+
+ // assert that fadeOutView's alpha is reset to 1f after the animation (hidden behind
// RemoteInputView)
- assertEquals(1f, crossFadeView.getAlpha());
+ assertEquals(1f, fadeOutView.getAlpha());
assertFalse(view.isAnimatingAppearance());
assertEquals(View.VISIBLE, view.getVisibility());
assertEquals(1f, view.getAlpha());
@@ -415,20 +423,27 @@
mDependency,
TestableLooper.get(this));
ExpandableNotificationRow row = helper.createRow();
- FrameLayout remoteInputViewParent = new FrameLayout(mContext);
RemoteInputView view = RemoteInputView.inflate(mContext, null, row.getEntry(), mController);
- remoteInputViewParent.addView(view);
bindController(view, row.getEntry());
+ View fadeInView = new View(mContext);
+ fadeInView.setId(com.android.internal.R.id.actions_container_layout);
+
+ FrameLayout parent = new FrameLayout(mContext);
+ parent.addView(view);
+ parent.addView(fadeInView);
+
// Start defocus animation
- view.onDefocus(true, false);
+ view.onDefocus(true /* animate */, false /* logClose */, null /* doAfterDefocus */);
assertEquals(View.VISIBLE, view.getVisibility());
+ assertEquals(0f, fadeInView.getAlpha());
// fast forward to end of animation
mAnimatorTestRule.advanceTimeBy(ANIMATION_DURATION_STANDARD);
// assert that RemoteInputView is no longer visible
assertEquals(View.GONE, view.getVisibility());
+ assertEquals(1f, fadeInView.getAlpha());
}
// NOTE: because we're refactoring the RemoteInputView and moving logic into the
diff --git a/core/java/android/nfc/BeamShareData.aidl b/packages/SystemUI/tests/src/com/android/systemui/stylus/FixedCapacityBatteryState.kt
similarity index 63%
rename from core/java/android/nfc/BeamShareData.aidl
rename to packages/SystemUI/tests/src/com/android/systemui/stylus/FixedCapacityBatteryState.kt
index a47e240..7e01088 100644
--- a/core/java/android/nfc/BeamShareData.aidl
+++ b/packages/SystemUI/tests/src/com/android/systemui/stylus/FixedCapacityBatteryState.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,6 +14,12 @@
* limitations under the License.
*/
-package android.nfc;
+package com.android.systemui.stylus
-parcelable BeamShareData;
+import android.hardware.BatteryState
+
+class FixedCapacityBatteryState(private val capacity: Float) : BatteryState() {
+ override fun getCapacity() = capacity
+ override fun getStatus() = 0
+ override fun isPresent() = true
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusFirstUsageListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusFirstUsageListenerTest.kt
deleted file mode 100644
index 8dd088f..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusFirstUsageListenerTest.kt
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.systemui.stylus
-
-import android.content.Context
-import android.hardware.BatteryState
-import android.hardware.input.InputManager
-import android.os.Handler
-import android.testing.AndroidTestingRunner
-import android.view.InputDevice
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
-import com.android.systemui.util.concurrency.FakeExecutor
-import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.whenever
-import com.android.systemui.util.time.FakeSystemClock
-import org.junit.Before
-import org.junit.Ignore
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.Mockito.never
-import org.mockito.Mockito.times
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.verifyNoMoreInteractions
-import org.mockito.Mockito.verifyZeroInteractions
-import org.mockito.MockitoAnnotations
-
-@RunWith(AndroidTestingRunner::class)
-@SmallTest
-@Ignore("TODO(b/20579491): unignore on main")
-class StylusFirstUsageListenerTest : SysuiTestCase() {
- @Mock lateinit var context: Context
- @Mock lateinit var inputManager: InputManager
- @Mock lateinit var stylusManager: StylusManager
- @Mock lateinit var featureFlags: FeatureFlags
- @Mock lateinit var internalStylusDevice: InputDevice
- @Mock lateinit var otherDevice: InputDevice
- @Mock lateinit var externalStylusDevice: InputDevice
- @Mock lateinit var batteryState: BatteryState
- @Mock lateinit var handler: Handler
-
- private lateinit var stylusListener: StylusFirstUsageListener
-
- @Before
- fun setUp() {
- MockitoAnnotations.initMocks(this)
- whenever(featureFlags.isEnabled(Flags.TRACK_STYLUS_EVER_USED)).thenReturn(true)
- whenever(inputManager.isStylusEverUsed(context)).thenReturn(false)
-
- stylusListener =
- StylusFirstUsageListener(
- context,
- inputManager,
- stylusManager,
- featureFlags,
- EXECUTOR,
- handler
- )
- stylusListener.hasStarted = false
-
- whenever(handler.post(any())).thenAnswer {
- (it.arguments[0] as Runnable).run()
- true
- }
-
- whenever(otherDevice.supportsSource(InputDevice.SOURCE_STYLUS)).thenReturn(false)
- whenever(internalStylusDevice.supportsSource(InputDevice.SOURCE_STYLUS)).thenReturn(true)
- whenever(internalStylusDevice.isExternal).thenReturn(false)
- whenever(externalStylusDevice.supportsSource(InputDevice.SOURCE_STYLUS)).thenReturn(true)
- whenever(externalStylusDevice.isExternal).thenReturn(true)
-
- whenever(inputManager.inputDeviceIds).thenReturn(intArrayOf())
- whenever(inputManager.getInputDevice(OTHER_DEVICE_ID)).thenReturn(otherDevice)
- whenever(inputManager.getInputDevice(INTERNAL_STYLUS_DEVICE_ID))
- .thenReturn(internalStylusDevice)
- whenever(inputManager.getInputDevice(EXTERNAL_STYLUS_DEVICE_ID))
- .thenReturn(externalStylusDevice)
- }
-
- @Test
- fun start_flagDisabled_doesNotRegister() {
- whenever(featureFlags.isEnabled(Flags.TRACK_STYLUS_EVER_USED)).thenReturn(false)
-
- stylusListener.start()
-
- verify(stylusManager, never()).registerCallback(any())
- verify(inputManager, never()).setStylusEverUsed(context, true)
- }
-
- @Test
- fun start_toggleHasStarted() {
- stylusListener.start()
-
- assert(stylusListener.hasStarted)
- }
-
- @Test
- fun start_hasStarted_doesNotRegister() {
- stylusListener.hasStarted = true
-
- stylusListener.start()
-
- verify(stylusManager, never()).registerCallback(any())
- }
-
- @Test
- fun start_hostDeviceDoesNotSupportStylus_doesNotRegister() {
- whenever(inputManager.inputDeviceIds).thenReturn(intArrayOf(OTHER_DEVICE_ID))
-
- stylusListener.start()
-
- verify(stylusManager, never()).registerCallback(any())
- verify(inputManager, never()).setStylusEverUsed(context, true)
- }
-
- @Test
- fun start_stylusEverUsed_doesNotRegister() {
- whenever(inputManager.inputDeviceIds)
- .thenReturn(intArrayOf(OTHER_DEVICE_ID, INTERNAL_STYLUS_DEVICE_ID))
- whenever(inputManager.isStylusEverUsed(context)).thenReturn(true)
-
- stylusListener.start()
-
- verify(stylusManager, never()).registerCallback(any())
- verify(inputManager, never()).setStylusEverUsed(context, true)
- }
-
- @Test
- fun start_hostDeviceSupportsStylus_registersListener() {
- whenever(inputManager.inputDeviceIds)
- .thenReturn(intArrayOf(OTHER_DEVICE_ID, INTERNAL_STYLUS_DEVICE_ID))
-
- stylusListener.start()
-
- verify(stylusManager).registerCallback(any())
- verify(inputManager, never()).setStylusEverUsed(context, true)
- }
-
- @Test
- fun onStylusAdded_hasNotStarted_doesNotRegisterListener() {
- stylusListener.hasStarted = false
-
- stylusListener.onStylusAdded(INTERNAL_STYLUS_DEVICE_ID)
-
- verifyZeroInteractions(inputManager)
- }
-
- @Test
- fun onStylusAdded_internalStylus_registersListener() {
- stylusListener.hasStarted = true
-
- stylusListener.onStylusAdded(INTERNAL_STYLUS_DEVICE_ID)
-
- verify(inputManager, times(1))
- .addInputDeviceBatteryListener(INTERNAL_STYLUS_DEVICE_ID, EXECUTOR, stylusListener)
- }
-
- @Test
- fun onStylusAdded_externalStylus_doesNotRegisterListener() {
- stylusListener.hasStarted = true
-
- stylusListener.onStylusAdded(EXTERNAL_STYLUS_DEVICE_ID)
-
- verify(inputManager, never()).addInputDeviceBatteryListener(any(), any(), any())
- }
-
- @Test
- fun onStylusAdded_otherDevice_doesNotRegisterListener() {
- stylusListener.onStylusAdded(OTHER_DEVICE_ID)
-
- verify(inputManager, never()).addInputDeviceBatteryListener(any(), any(), any())
- }
-
- @Test
- fun onStylusRemoved_registeredDevice_unregistersListener() {
- stylusListener.hasStarted = true
- stylusListener.onStylusAdded(INTERNAL_STYLUS_DEVICE_ID)
-
- stylusListener.onStylusRemoved(INTERNAL_STYLUS_DEVICE_ID)
-
- verify(inputManager, times(1))
- .removeInputDeviceBatteryListener(INTERNAL_STYLUS_DEVICE_ID, stylusListener)
- }
-
- @Test
- fun onStylusRemoved_hasNotStarted_doesNotUnregisterListener() {
- stylusListener.hasStarted = false
- stylusListener.onStylusAdded(INTERNAL_STYLUS_DEVICE_ID)
-
- stylusListener.onStylusRemoved(INTERNAL_STYLUS_DEVICE_ID)
-
- verifyZeroInteractions(inputManager)
- }
-
- @Test
- fun onStylusRemoved_unregisteredDevice_doesNotUnregisterListener() {
- stylusListener.hasStarted = true
-
- stylusListener.onStylusRemoved(INTERNAL_STYLUS_DEVICE_ID)
-
- verifyNoMoreInteractions(inputManager)
- }
-
- @Test
- fun onStylusBluetoothConnected_updateStylusFlagAndUnregisters() {
- stylusListener.hasStarted = true
- stylusListener.onStylusAdded(INTERNAL_STYLUS_DEVICE_ID)
-
- stylusListener.onStylusBluetoothConnected(EXTERNAL_STYLUS_DEVICE_ID, "ANY")
-
- verify(inputManager).setStylusEverUsed(context, true)
- verify(inputManager, times(1))
- .removeInputDeviceBatteryListener(INTERNAL_STYLUS_DEVICE_ID, stylusListener)
- verify(stylusManager).unregisterCallback(stylusListener)
- }
-
- @Test
- fun onStylusBluetoothConnected_hasNotStarted_doesNoting() {
- stylusListener.hasStarted = false
- stylusListener.onStylusAdded(INTERNAL_STYLUS_DEVICE_ID)
-
- stylusListener.onStylusBluetoothConnected(EXTERNAL_STYLUS_DEVICE_ID, "ANY")
-
- verifyZeroInteractions(inputManager)
- verifyZeroInteractions(stylusManager)
- }
-
- @Test
- fun onBatteryStateChanged_batteryPresent_updateStylusFlagAndUnregisters() {
- stylusListener.hasStarted = true
- stylusListener.onStylusAdded(INTERNAL_STYLUS_DEVICE_ID)
- whenever(batteryState.isPresent).thenReturn(true)
-
- stylusListener.onBatteryStateChanged(0, 1, batteryState)
-
- verify(inputManager).setStylusEverUsed(context, true)
- verify(inputManager, times(1))
- .removeInputDeviceBatteryListener(INTERNAL_STYLUS_DEVICE_ID, stylusListener)
- verify(stylusManager).unregisterCallback(stylusListener)
- }
-
- @Test
- fun onBatteryStateChanged_batteryNotPresent_doesNotUpdateFlagOrUnregister() {
- stylusListener.hasStarted = true
- stylusListener.onStylusAdded(INTERNAL_STYLUS_DEVICE_ID)
- whenever(batteryState.isPresent).thenReturn(false)
-
- stylusListener.onBatteryStateChanged(0, 1, batteryState)
-
- verifyZeroInteractions(stylusManager)
- verify(inputManager, never())
- .removeInputDeviceBatteryListener(INTERNAL_STYLUS_DEVICE_ID, stylusListener)
- }
-
- @Test
- fun onBatteryStateChanged_hasNotStarted_doesNothing() {
- stylusListener.hasStarted = false
- stylusListener.onStylusAdded(INTERNAL_STYLUS_DEVICE_ID)
- whenever(batteryState.isPresent).thenReturn(false)
-
- stylusListener.onBatteryStateChanged(0, 1, batteryState)
-
- verifyZeroInteractions(inputManager)
- verifyZeroInteractions(stylusManager)
- }
-
- companion object {
- private const val OTHER_DEVICE_ID = 0
- private const val INTERNAL_STYLUS_DEVICE_ID = 1
- private const val EXTERNAL_STYLUS_DEVICE_ID = 2
- private val EXECUTOR = FakeExecutor(FakeSystemClock())
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusManagerTest.kt
index 984de5b..a08e002 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusManagerTest.kt
@@ -17,44 +17,43 @@
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
+import android.hardware.BatteryState
import android.hardware.input.InputManager
import android.os.Handler
import android.testing.AndroidTestingRunner
import android.view.InputDevice
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.whenever
import java.util.concurrent.Executor
import org.junit.Before
-import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
+import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.inOrder
import org.mockito.Mockito.never
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyNoMoreInteractions
+import org.mockito.Mockito.verifyZeroInteractions
import org.mockito.MockitoAnnotations
@RunWith(AndroidTestingRunner::class)
@SmallTest
-@Ignore("b/257936830 until bt APIs")
class StylusManagerTest : SysuiTestCase() {
@Mock lateinit var inputManager: InputManager
-
@Mock lateinit var stylusDevice: InputDevice
-
@Mock lateinit var btStylusDevice: InputDevice
-
@Mock lateinit var otherDevice: InputDevice
-
+ @Mock lateinit var batteryState: BatteryState
@Mock lateinit var bluetoothAdapter: BluetoothAdapter
-
@Mock lateinit var bluetoothDevice: BluetoothDevice
-
@Mock lateinit var handler: Handler
+ @Mock lateinit var featureFlags: FeatureFlags
@Mock lateinit var stylusCallback: StylusManager.StylusCallback
@@ -75,36 +74,61 @@
true
}
- stylusManager = StylusManager(inputManager, bluetoothAdapter, handler, EXECUTOR)
-
- stylusManager.registerCallback(stylusCallback)
-
- stylusManager.registerBatteryCallback(stylusBatteryCallback)
+ stylusManager =
+ StylusManager(mContext, inputManager, bluetoothAdapter, handler, EXECUTOR, featureFlags)
whenever(otherDevice.supportsSource(InputDevice.SOURCE_STYLUS)).thenReturn(false)
whenever(stylusDevice.supportsSource(InputDevice.SOURCE_STYLUS)).thenReturn(true)
whenever(btStylusDevice.supportsSource(InputDevice.SOURCE_STYLUS)).thenReturn(true)
- // whenever(stylusDevice.bluetoothAddress).thenReturn(null)
- // whenever(btStylusDevice.bluetoothAddress).thenReturn(STYLUS_BT_ADDRESS)
+ whenever(stylusDevice.bluetoothAddress).thenReturn(null)
+ whenever(btStylusDevice.bluetoothAddress).thenReturn(STYLUS_BT_ADDRESS)
whenever(inputManager.getInputDevice(OTHER_DEVICE_ID)).thenReturn(otherDevice)
whenever(inputManager.getInputDevice(STYLUS_DEVICE_ID)).thenReturn(stylusDevice)
whenever(inputManager.getInputDevice(BT_STYLUS_DEVICE_ID)).thenReturn(btStylusDevice)
whenever(inputManager.inputDeviceIds).thenReturn(intArrayOf(STYLUS_DEVICE_ID))
+ whenever(inputManager.isStylusEverUsed(mContext)).thenReturn(false)
whenever(bluetoothAdapter.getRemoteDevice(STYLUS_BT_ADDRESS)).thenReturn(bluetoothDevice)
whenever(bluetoothDevice.address).thenReturn(STYLUS_BT_ADDRESS)
+
+ whenever(featureFlags.isEnabled(Flags.TRACK_STYLUS_EVER_USED)).thenReturn(true)
+
+ stylusManager.startListener()
+ stylusManager.registerCallback(stylusCallback)
+ stylusManager.registerBatteryCallback(stylusBatteryCallback)
+ clearInvocations(inputManager)
}
@Test
- fun startListener_registersInputDeviceListener() {
+ fun startListener_hasNotStarted_registersInputDeviceListener() {
+ stylusManager =
+ StylusManager(mContext, inputManager, bluetoothAdapter, handler, EXECUTOR, featureFlags)
+
stylusManager.startListener()
verify(inputManager, times(1)).registerInputDeviceListener(any(), any())
}
@Test
+ fun startListener_hasStarted_doesNothing() {
+ stylusManager.startListener()
+
+ verifyZeroInteractions(inputManager)
+ }
+
+ @Test
+ fun onInputDeviceAdded_hasNotStarted_doesNothing() {
+ stylusManager =
+ StylusManager(mContext, inputManager, bluetoothAdapter, handler, EXECUTOR, featureFlags)
+
+ stylusManager.onInputDeviceAdded(STYLUS_DEVICE_ID)
+
+ verifyZeroInteractions(stylusCallback)
+ }
+
+ @Test
fun onInputDeviceAdded_multipleRegisteredCallbacks_callsAll() {
stylusManager.registerCallback(otherStylusCallback)
@@ -117,6 +141,26 @@
}
@Test
+ fun onInputDeviceAdded_internalStylus_registersBatteryListener() {
+ whenever(stylusDevice.isExternal).thenReturn(false)
+
+ stylusManager.onInputDeviceAdded(STYLUS_DEVICE_ID)
+
+ verify(inputManager, times(1))
+ .addInputDeviceBatteryListener(STYLUS_DEVICE_ID, EXECUTOR, stylusManager)
+ }
+
+ @Test
+ fun onInputDeviceAdded_externalStylus_doesNotRegisterbatteryListener() {
+ whenever(stylusDevice.isExternal).thenReturn(true)
+
+ stylusManager.onInputDeviceAdded(STYLUS_DEVICE_ID)
+
+ verify(inputManager, never())
+ .addInputDeviceBatteryListener(STYLUS_DEVICE_ID, EXECUTOR, stylusManager)
+ }
+
+ @Test
fun onInputDeviceAdded_stylus_callsCallbacksOnStylusAdded() {
stylusManager.onInputDeviceAdded(STYLUS_DEVICE_ID)
@@ -125,6 +169,20 @@
}
@Test
+ fun onInputDeviceAdded_btStylus_firstUsed_callsCallbacksOnStylusFirstUsed() {
+ stylusManager.onInputDeviceAdded(BT_STYLUS_DEVICE_ID)
+
+ verify(stylusCallback, times(1)).onStylusFirstUsed()
+ }
+
+ @Test
+ fun onInputDeviceAdded_btStylus_firstUsed_setsFlag() {
+ stylusManager.onInputDeviceAdded(BT_STYLUS_DEVICE_ID)
+
+ verify(inputManager, times(1)).setStylusEverUsed(mContext, true)
+ }
+
+ @Test
fun onInputDeviceAdded_btStylus_callsCallbacksWithAddress() {
stylusManager.onInputDeviceAdded(BT_STYLUS_DEVICE_ID)
@@ -143,9 +201,19 @@
}
@Test
+ fun onInputDeviceChanged_hasNotStarted_doesNothing() {
+ stylusManager =
+ StylusManager(mContext, inputManager, bluetoothAdapter, handler, EXECUTOR, featureFlags)
+
+ stylusManager.onInputDeviceChanged(STYLUS_DEVICE_ID)
+
+ verifyZeroInteractions(stylusCallback)
+ }
+
+ @Test
fun onInputDeviceChanged_multipleRegisteredCallbacks_callsAll() {
stylusManager.onInputDeviceAdded(STYLUS_DEVICE_ID)
- // whenever(stylusDevice.bluetoothAddress).thenReturn(STYLUS_BT_ADDRESS)
+ whenever(stylusDevice.bluetoothAddress).thenReturn(STYLUS_BT_ADDRESS)
stylusManager.registerCallback(otherStylusCallback)
stylusManager.onInputDeviceChanged(STYLUS_DEVICE_ID)
@@ -159,7 +227,7 @@
@Test
fun onInputDeviceChanged_stylusNewBtConnection_callsCallbacks() {
stylusManager.onInputDeviceAdded(STYLUS_DEVICE_ID)
- // whenever(stylusDevice.bluetoothAddress).thenReturn(STYLUS_BT_ADDRESS)
+ whenever(stylusDevice.bluetoothAddress).thenReturn(STYLUS_BT_ADDRESS)
stylusManager.onInputDeviceChanged(STYLUS_DEVICE_ID)
@@ -170,7 +238,7 @@
@Test
fun onInputDeviceChanged_stylusLostBtConnection_callsCallbacks() {
stylusManager.onInputDeviceAdded(BT_STYLUS_DEVICE_ID)
- // whenever(btStylusDevice.bluetoothAddress).thenReturn(null)
+ whenever(btStylusDevice.bluetoothAddress).thenReturn(null)
stylusManager.onInputDeviceChanged(BT_STYLUS_DEVICE_ID)
@@ -198,6 +266,17 @@
}
@Test
+ fun onInputDeviceRemoved_hasNotStarted_doesNothing() {
+ stylusManager =
+ StylusManager(mContext, inputManager, bluetoothAdapter, handler, EXECUTOR, featureFlags)
+ stylusManager.onInputDeviceAdded(STYLUS_DEVICE_ID)
+
+ stylusManager.onInputDeviceRemoved(STYLUS_DEVICE_ID)
+
+ verifyZeroInteractions(stylusCallback)
+ }
+
+ @Test
fun onInputDeviceRemoved_multipleRegisteredCallbacks_callsAll() {
stylusManager.onInputDeviceAdded(STYLUS_DEVICE_ID)
stylusManager.registerCallback(otherStylusCallback)
@@ -219,6 +298,16 @@
}
@Test
+ fun onInputDeviceRemoved_unregistersBatteryListener() {
+ stylusManager.onInputDeviceAdded(STYLUS_DEVICE_ID)
+
+ stylusManager.onInputDeviceRemoved(STYLUS_DEVICE_ID)
+
+ verify(inputManager, times(1))
+ .removeInputDeviceBatteryListener(STYLUS_DEVICE_ID, stylusManager)
+ }
+
+ @Test
fun onInputDeviceRemoved_btStylus_callsCallbacks() {
stylusManager.onInputDeviceAdded(BT_STYLUS_DEVICE_ID)
@@ -326,6 +415,59 @@
.onStylusBluetoothChargingStateChanged(any(), any(), any())
}
+ @Test
+ fun onBatteryStateChanged_batteryPresent_stylusNeverUsed_updateEverUsedFlag() {
+ whenever(batteryState.isPresent).thenReturn(true)
+
+ stylusManager.onBatteryStateChanged(STYLUS_DEVICE_ID, 1, batteryState)
+
+ verify(inputManager).setStylusEverUsed(mContext, true)
+ }
+
+ @Test
+ fun onBatteryStateChanged_batteryPresent_stylusNeverUsed_executesStylusFirstUsed() {
+ whenever(batteryState.isPresent).thenReturn(true)
+
+ stylusManager.onBatteryStateChanged(STYLUS_DEVICE_ID, 1, batteryState)
+
+ verify(stylusCallback, times(1)).onStylusFirstUsed()
+ }
+
+ @Test
+ fun onBatteryStateChanged_batteryPresent_stylusUsed_doesNotUpdateEverUsedFlag() {
+ whenever(inputManager.isStylusEverUsed(mContext)).thenReturn(true)
+ whenever(batteryState.isPresent).thenReturn(true)
+
+ stylusManager.onBatteryStateChanged(STYLUS_DEVICE_ID, 1, batteryState)
+
+ verify(inputManager, never()).setStylusEverUsed(mContext, true)
+ }
+
+ @Test
+ fun onBatteryStateChanged_batteryNotPresent_doesNotUpdateEverUsedFlag() {
+ whenever(batteryState.isPresent).thenReturn(false)
+
+ stylusManager.onBatteryStateChanged(STYLUS_DEVICE_ID, 1, batteryState)
+
+ verify(inputManager, never())
+ .removeInputDeviceBatteryListener(STYLUS_DEVICE_ID, stylusManager)
+ }
+
+ @Test
+ fun onBatteryStateChanged_hasNotStarted_doesNothing() {
+ stylusManager.onBatteryStateChanged(STYLUS_DEVICE_ID, 1, batteryState)
+
+ verifyZeroInteractions(inputManager)
+ }
+
+ @Test
+ fun onBatteryStateChanged_executesBatteryCallbacks() {
+ stylusManager.onBatteryStateChanged(STYLUS_DEVICE_ID, 1, batteryState)
+
+ verify(stylusBatteryCallback, times(1))
+ .onStylusUsiBatteryStateChanged(STYLUS_DEVICE_ID, 1, batteryState)
+ }
+
companion object {
private val EXECUTOR = Executor { r -> r.run() }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusUsiPowerStartableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusUsiPowerStartableTest.kt
index ff382a3..1cccd65c8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusUsiPowerStartableTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusUsiPowerStartableTest.kt
@@ -25,17 +25,15 @@
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.util.mockito.whenever
-import java.util.concurrent.Executor
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
-import org.mockito.Mockito.inOrder
import org.mockito.Mockito.mock
-import org.mockito.Mockito.never
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyNoMoreInteractions
+import org.mockito.Mockito.verifyZeroInteractions
import org.mockito.MockitoAnnotations
@RunWith(AndroidTestingRunner::class)
@@ -60,7 +58,6 @@
inputManager,
stylusUsiPowerUi,
featureFlags,
- DIRECT_EXECUTOR,
)
whenever(featureFlags.isEnabled(Flags.ENABLE_USI_BATTERY_NOTIFICATIONS)).thenReturn(true)
@@ -79,40 +76,19 @@
}
@Test
- fun start_addsBatteryListenerForInternalStylus() {
+ fun start_hostDeviceDoesNotSupportStylus_doesNotRegister() {
+ whenever(inputManager.inputDeviceIds).thenReturn(intArrayOf(EXTERNAL_DEVICE_ID))
+
startable.start()
- verify(inputManager, times(1))
- .addInputDeviceBatteryListener(STYLUS_DEVICE_ID, DIRECT_EXECUTOR, startable)
+ verifyZeroInteractions(stylusManager)
}
@Test
- fun onStylusAdded_internalStylus_addsBatteryListener() {
- startable.onStylusAdded(STYLUS_DEVICE_ID)
+ fun start_initStylusUsiPowerUi() {
+ startable.start()
- verify(inputManager, times(1))
- .addInputDeviceBatteryListener(STYLUS_DEVICE_ID, DIRECT_EXECUTOR, startable)
- }
-
- @Test
- fun onStylusAdded_externalStylus_doesNotAddBatteryListener() {
- startable.onStylusAdded(EXTERNAL_DEVICE_ID)
-
- verify(inputManager, never())
- .addInputDeviceBatteryListener(EXTERNAL_DEVICE_ID, DIRECT_EXECUTOR, startable)
- }
-
- @Test
- fun onStylusRemoved_registeredStylus_removesBatteryListener() {
- startable.onStylusAdded(STYLUS_DEVICE_ID)
- startable.onStylusRemoved(STYLUS_DEVICE_ID)
-
- inOrder(inputManager).let {
- it.verify(inputManager, times(1))
- .addInputDeviceBatteryListener(STYLUS_DEVICE_ID, DIRECT_EXECUTOR, startable)
- it.verify(inputManager, times(1))
- .removeInputDeviceBatteryListener(STYLUS_DEVICE_ID, startable)
- }
+ verify(stylusUsiPowerUi, times(1)).init()
}
@Test
@@ -130,28 +106,34 @@
}
@Test
- fun onBatteryStateChanged_batteryPresent_refreshesNotification() {
- val batteryState = mock(BatteryState::class.java)
- whenever(batteryState.isPresent).thenReturn(true)
+ fun onStylusUsiBatteryStateChanged_batteryPresentValidCapacity_refreshesNotification() {
+ val batteryState = FixedCapacityBatteryState(0.1f)
- startable.onBatteryStateChanged(STYLUS_DEVICE_ID, 123, batteryState)
+ startable.onStylusUsiBatteryStateChanged(STYLUS_DEVICE_ID, 123, batteryState)
- verify(stylusUsiPowerUi, times(1)).updateBatteryState(batteryState)
+ verify(stylusUsiPowerUi, times(1)).updateBatteryState(STYLUS_DEVICE_ID, batteryState)
}
@Test
- fun onBatteryStateChanged_batteryNotPresent_noop() {
+ fun onStylusUsiBatteryStateChanged_batteryPresentInvalidCapacity_noop() {
+ val batteryState = FixedCapacityBatteryState(0f)
+
+ startable.onStylusUsiBatteryStateChanged(STYLUS_DEVICE_ID, 123, batteryState)
+
+ verifyNoMoreInteractions(stylusUsiPowerUi)
+ }
+
+ @Test
+ fun onStylusUsiBatteryStateChanged_batteryNotPresent_noop() {
val batteryState = mock(BatteryState::class.java)
whenever(batteryState.isPresent).thenReturn(false)
- startable.onBatteryStateChanged(STYLUS_DEVICE_ID, 123, batteryState)
+ startable.onStylusUsiBatteryStateChanged(STYLUS_DEVICE_ID, 123, batteryState)
verifyNoMoreInteractions(stylusUsiPowerUi)
}
companion object {
- private val DIRECT_EXECUTOR = Executor { r -> r.run() }
-
private const val EXTERNAL_DEVICE_ID = 0
private const val STYLUS_DEVICE_ID = 1
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusUsiPowerUiTest.kt b/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusUsiPowerUiTest.kt
index 5987550..1e81dc7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusUsiPowerUiTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusUsiPowerUiTest.kt
@@ -16,8 +16,12 @@
package com.android.systemui.stylus
-import android.hardware.BatteryState
+import android.app.Notification
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
import android.hardware.input.InputManager
+import android.os.Bundle
import android.os.Handler
import android.testing.AndroidTestingRunner
import android.view.InputDevice
@@ -26,14 +30,22 @@
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import junit.framework.Assert.assertEquals
import org.junit.Before
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.Captor
import org.mockito.Mock
+import org.mockito.Mockito.doNothing
import org.mockito.Mockito.inOrder
+import org.mockito.Mockito.never
+import org.mockito.Mockito.spy
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyNoMoreInteractions
@@ -46,13 +58,19 @@
@Mock lateinit var inputManager: InputManager
@Mock lateinit var handler: Handler
@Mock lateinit var btStylusDevice: InputDevice
+ @Captor lateinit var notificationCaptor: ArgumentCaptor<Notification>
private lateinit var stylusUsiPowerUi: StylusUsiPowerUI
+ private lateinit var broadcastReceiver: BroadcastReceiver
+ private lateinit var contextSpy: Context
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
+ contextSpy = spy(mContext)
+ doNothing().whenever(contextSpy).startActivity(any())
+
whenever(handler.post(any())).thenAnswer {
(it.arguments[0] as Runnable).run()
true
@@ -63,56 +81,77 @@
whenever(btStylusDevice.supportsSource(InputDevice.SOURCE_STYLUS)).thenReturn(true)
// whenever(btStylusDevice.bluetoothAddress).thenReturn("SO:ME:AD:DR:ES")
- stylusUsiPowerUi = StylusUsiPowerUI(mContext, notificationManager, inputManager, handler)
+ stylusUsiPowerUi = StylusUsiPowerUI(contextSpy, notificationManager, inputManager, handler)
+ broadcastReceiver = stylusUsiPowerUi.receiver
+ }
+
+ @Test
+ fun updateBatteryState_capacityZero_noop() {
+ stylusUsiPowerUi.updateBatteryState(0, FixedCapacityBatteryState(0f))
+
+ verifyNoMoreInteractions(notificationManager)
}
@Test
fun updateBatteryState_capacityBelowThreshold_notifies() {
- stylusUsiPowerUi.updateBatteryState(FixedCapacityBatteryState(0.1f))
+ stylusUsiPowerUi.updateBatteryState(0, FixedCapacityBatteryState(0.1f))
- verify(notificationManager, times(1)).notify(eq(R.string.stylus_battery_low), any())
+ verify(notificationManager, times(1))
+ .notify(eq(R.string.stylus_battery_low_percentage), any())
verifyNoMoreInteractions(notificationManager)
}
@Test
fun updateBatteryState_capacityAboveThreshold_cancelsNotificattion() {
- stylusUsiPowerUi.updateBatteryState(FixedCapacityBatteryState(0.8f))
+ stylusUsiPowerUi.updateBatteryState(0, FixedCapacityBatteryState(0.8f))
- verify(notificationManager, times(1)).cancel(R.string.stylus_battery_low)
+ verify(notificationManager, times(1)).cancel(R.string.stylus_battery_low_percentage)
verifyNoMoreInteractions(notificationManager)
}
@Test
fun updateBatteryState_existingNotification_capacityAboveThreshold_cancelsNotification() {
- stylusUsiPowerUi.updateBatteryState(FixedCapacityBatteryState(0.1f))
- stylusUsiPowerUi.updateBatteryState(FixedCapacityBatteryState(0.8f))
+ stylusUsiPowerUi.updateBatteryState(0, FixedCapacityBatteryState(0.1f))
+ stylusUsiPowerUi.updateBatteryState(0, FixedCapacityBatteryState(0.8f))
inOrder(notificationManager).let {
- it.verify(notificationManager, times(1)).notify(eq(R.string.stylus_battery_low), any())
- it.verify(notificationManager, times(1)).cancel(R.string.stylus_battery_low)
+ it.verify(notificationManager, times(1))
+ .notify(eq(R.string.stylus_battery_low_percentage), any())
+ it.verify(notificationManager, times(1)).cancel(R.string.stylus_battery_low_percentage)
it.verifyNoMoreInteractions()
}
}
@Test
fun updateBatteryState_existingNotification_capacityBelowThreshold_updatesNotification() {
- stylusUsiPowerUi.updateBatteryState(FixedCapacityBatteryState(0.1f))
- stylusUsiPowerUi.updateBatteryState(FixedCapacityBatteryState(0.15f))
+ stylusUsiPowerUi.updateBatteryState(0, FixedCapacityBatteryState(0.1f))
+ stylusUsiPowerUi.updateBatteryState(0, FixedCapacityBatteryState(0.15f))
- verify(notificationManager, times(2)).notify(eq(R.string.stylus_battery_low), any())
+ verify(notificationManager, times(2))
+ .notify(eq(R.string.stylus_battery_low_percentage), notificationCaptor.capture())
+ assertEquals(
+ notificationCaptor.value.extras.getString(Notification.EXTRA_TITLE),
+ context.getString(R.string.stylus_battery_low_percentage, "15%")
+ )
+ assertEquals(
+ notificationCaptor.value.extras.getString(Notification.EXTRA_TEXT),
+ context.getString(R.string.stylus_battery_low_subtitle)
+ )
verifyNoMoreInteractions(notificationManager)
}
@Test
fun updateBatteryState_capacityAboveThenBelowThreshold_hidesThenShowsNotification() {
- stylusUsiPowerUi.updateBatteryState(FixedCapacityBatteryState(0.1f))
- stylusUsiPowerUi.updateBatteryState(FixedCapacityBatteryState(0.5f))
- stylusUsiPowerUi.updateBatteryState(FixedCapacityBatteryState(0.1f))
+ stylusUsiPowerUi.updateBatteryState(0, FixedCapacityBatteryState(0.1f))
+ stylusUsiPowerUi.updateBatteryState(0, FixedCapacityBatteryState(0.5f))
+ stylusUsiPowerUi.updateBatteryState(0, FixedCapacityBatteryState(0.1f))
inOrder(notificationManager).let {
- it.verify(notificationManager, times(1)).notify(eq(R.string.stylus_battery_low), any())
- it.verify(notificationManager, times(1)).cancel(R.string.stylus_battery_low)
- it.verify(notificationManager, times(1)).notify(eq(R.string.stylus_battery_low), any())
+ it.verify(notificationManager, times(1))
+ .notify(eq(R.string.stylus_battery_low_percentage), any())
+ it.verify(notificationManager, times(1)).cancel(R.string.stylus_battery_low_percentage)
+ it.verify(notificationManager, times(1))
+ .notify(eq(R.string.stylus_battery_low_percentage), any())
it.verifyNoMoreInteractions()
}
}
@@ -121,47 +160,66 @@
fun updateSuppression_noExistingNotification_cancelsNotification() {
stylusUsiPowerUi.updateSuppression(true)
- verify(notificationManager, times(1)).cancel(R.string.stylus_battery_low)
+ verify(notificationManager, times(1)).cancel(R.string.stylus_battery_low_percentage)
verifyNoMoreInteractions(notificationManager)
}
@Test
fun updateSuppression_existingNotification_cancelsNotification() {
- stylusUsiPowerUi.updateBatteryState(FixedCapacityBatteryState(0.1f))
+ stylusUsiPowerUi.updateBatteryState(0, FixedCapacityBatteryState(0.1f))
stylusUsiPowerUi.updateSuppression(true)
inOrder(notificationManager).let {
- it.verify(notificationManager, times(1)).notify(eq(R.string.stylus_battery_low), any())
- it.verify(notificationManager, times(1)).cancel(R.string.stylus_battery_low)
+ it.verify(notificationManager, times(1))
+ .notify(eq(R.string.stylus_battery_low_percentage), any())
+ it.verify(notificationManager, times(1)).cancel(R.string.stylus_battery_low_percentage)
it.verifyNoMoreInteractions()
}
}
@Test
@Ignore("TODO(b/257936830): get bt address once input api available")
- fun refresh_hasConnectedBluetoothStylus_doesNotNotify() {
+ fun refresh_hasConnectedBluetoothStylus_cancelsNotification() {
whenever(inputManager.inputDeviceIds).thenReturn(intArrayOf(0))
stylusUsiPowerUi.refresh()
- verifyNoMoreInteractions(notificationManager)
+ verify(notificationManager).cancel(R.string.stylus_battery_low_percentage)
}
@Test
@Ignore("TODO(b/257936830): get bt address once input api available")
fun refresh_hasConnectedBluetoothStylus_existingNotification_cancelsNotification() {
- stylusUsiPowerUi.updateBatteryState(FixedCapacityBatteryState(0.1f))
+ stylusUsiPowerUi.updateBatteryState(0, FixedCapacityBatteryState(0.1f))
whenever(inputManager.inputDeviceIds).thenReturn(intArrayOf(0))
stylusUsiPowerUi.refresh()
- verify(notificationManager).cancel(R.string.stylus_battery_low)
+ verify(notificationManager).cancel(R.string.stylus_battery_low_percentage)
}
- class FixedCapacityBatteryState(private val capacity: Float) : BatteryState() {
- override fun getCapacity() = capacity
- override fun getStatus() = 0
- override fun isPresent() = true
+ @Test
+ fun broadcastReceiver_clicked_hasInputDeviceId_startsUsiDetailsActivity() {
+ val intent = Intent(StylusUsiPowerUI.ACTION_CLICKED_LOW_BATTERY)
+ val activityIntentCaptor = argumentCaptor<Intent>()
+ stylusUsiPowerUi.updateBatteryState(1, FixedCapacityBatteryState(0.15f))
+ broadcastReceiver.onReceive(contextSpy, intent)
+
+ verify(contextSpy, times(1)).startActivity(activityIntentCaptor.capture())
+ assertThat(activityIntentCaptor.value.action)
+ .isEqualTo(StylusUsiPowerUI.ACTION_STYLUS_USI_DETAILS)
+ val args =
+ activityIntentCaptor.value.getExtra(StylusUsiPowerUI.KEY_SETTINGS_FRAGMENT_ARGS)
+ as Bundle
+ assertThat(args.getInt(StylusUsiPowerUI.KEY_DEVICE_INPUT_ID)).isEqualTo(1)
+ }
+
+ @Test
+ fun broadcastReceiver_clicked_nullInputDeviceId_doesNotStartActivity() {
+ val intent = Intent(StylusUsiPowerUI.ACTION_CLICKED_LOW_BATTERY)
+ broadcastReceiver.onReceive(contextSpy, intent)
+
+ verify(contextSpy, never()).startActivity(any())
}
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/MemoryTrackingTestCase.java b/packages/SystemUI/tests/utils/src/com/android/systemui/MemoryTrackingTestCase.java
index 3767fbe..3428553 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/MemoryTrackingTestCase.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/MemoryTrackingTestCase.java
@@ -40,24 +40,49 @@
public class MemoryTrackingTestCase extends SysuiTestCase {
private static File sFilesDir = null;
private static String sLatestTestClassName = null;
+ private static int sHeapCount = 0;
+ private static File sLatestBaselineHeapFile = null;
- @Before public void grabFilesDir() {
+ // Ideally, we would do this in @BeforeClass just once, but we need mContext to get the files
+ // dir, and that does not exist until @Before on each test method.
+ @Before
+ public void grabFilesDir() throws IOException {
+ // This should happen only once per suite
if (sFilesDir == null) {
sFilesDir = mContext.getFilesDir();
}
- sLatestTestClassName = getClass().getName();
+
+ // This will happen before the first test method in each class
+ if (sLatestTestClassName == null) {
+ sLatestTestClassName = getClass().getName();
+ sLatestBaselineHeapFile = dump("baseline" + (++sHeapCount), "before-test");
+ }
}
@AfterClass
public static void dumpHeap() throws IOException {
+ File afterTestHeap = dump(sLatestTestClassName, "after-test");
+ if (sLatestBaselineHeapFile != null && afterTestHeap != null) {
+ Log.w("MEMORY", "To compare heap to baseline (use go/ahat):");
+ Log.w("MEMORY", " adb pull " + sLatestBaselineHeapFile);
+ Log.w("MEMORY", " adb pull " + afterTestHeap);
+ Log.w("MEMORY",
+ " java -jar ahat.jar --baseline " + sLatestBaselineHeapFile.getName() + " "
+ + afterTestHeap.getName());
+ }
+ sLatestTestClassName = null;
+ }
+
+ private static File dump(String basename, String heapKind) throws IOException {
if (sFilesDir == null) {
Log.e("MEMORY", "Somehow no test cases??");
- return;
+ return null;
}
mockitoTearDown();
- Log.w("MEMORY", "about to dump heap");
- File path = new File(sFilesDir, sLatestTestClassName + ".ahprof");
+ Log.w("MEMORY", "about to dump " + heapKind + " heap");
+ File path = new File(sFilesDir, basename + ".ahprof");
Debug.dumpHprofData(path.getPath());
- Log.w("MEMORY", "did it! Location: " + path);
+ Log.w("MEMORY", "Success! Location: " + path);
+ return path;
}
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/udfps/FakeOverlapDetector.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/udfps/FakeOverlapDetector.kt
index 8176dd0..1bdee36 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/udfps/FakeOverlapDetector.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/udfps/FakeOverlapDetector.kt
@@ -19,9 +19,10 @@
import android.graphics.Rect
class FakeOverlapDetector : OverlapDetector {
- var shouldReturn: Boolean = false
+ var shouldReturn: Map<Int, Boolean> = mapOf()
override fun isGoodOverlap(touchData: NormalizedTouchData, nativeSensorBounds: Rect): Boolean {
- return shouldReturn
+ return shouldReturn[touchData.pointerId]
+ ?: error("Unexpected PointerId not declared in TestCase currentPointers")
}
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
index 39d2eca..15b4736 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
@@ -52,6 +52,9 @@
private val _isDozing = MutableStateFlow(false)
override val isDozing: Flow<Boolean> = _isDozing
+ private val _isAodAvailable = MutableStateFlow(false)
+ override val isAodAvailable: Flow<Boolean> = _isAodAvailable
+
private val _isDreaming = MutableStateFlow(false)
override val isDreaming: Flow<Boolean> = _isDreaming
@@ -126,6 +129,10 @@
_isDozing.value = isDozing
}
+ fun setAodAvailable(isAodAvailable: Boolean) {
+ _isAodAvailable.value = isAodAvailable
+ }
+
fun setDreamingWithOverlay(isDreaming: Boolean) {
_isDreamingWithOverlay.value = isDreaming
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java
index 2d6d29a..926c6c5 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java
@@ -98,6 +98,10 @@
}
@Override
+ public void removeAllIconsForExternalSlot(String slot) {
+ }
+
+ @Override
public void setIconAccessibilityLiveRegion(String slot, int mode) {
}
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedComponent.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedComponent.kt
index 5a868a4..cfb959e 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedComponent.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedComponent.kt
@@ -22,8 +22,8 @@
import android.os.Handler
import android.view.IWindowManager
import com.android.systemui.unfold.config.UnfoldTransitionConfig
-import com.android.systemui.unfold.dagger.UnfoldBackground
import com.android.systemui.unfold.dagger.UnfoldMain
+import com.android.systemui.unfold.dagger.UnfoldSingleThreadBg
import com.android.systemui.unfold.updates.FoldProvider
import com.android.systemui.unfold.updates.RotationChangeProvider
import com.android.systemui.unfold.updates.screen.ScreenStatusProvider
@@ -58,7 +58,7 @@
@BindsInstance sensorManager: SensorManager,
@BindsInstance @UnfoldMain handler: Handler,
@BindsInstance @UnfoldMain executor: Executor,
- @BindsInstance @UnfoldBackground backgroundExecutor: Executor,
+ @BindsInstance @UnfoldSingleThreadBg singleThreadBgExecutor: Executor,
@BindsInstance @UnfoldTransitionATracePrefix tracingTagPrefix: String,
@BindsInstance windowManager: IWindowManager,
@BindsInstance contentResolver: ContentResolver = context.contentResolver
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedModule.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedModule.kt
index 3fa5469..31616fa 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedModule.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedModule.kt
@@ -16,9 +16,7 @@
package com.android.systemui.unfold
-import android.hardware.SensorManager
import com.android.systemui.unfold.config.UnfoldTransitionConfig
-import com.android.systemui.unfold.dagger.UnfoldBackground
import com.android.systemui.unfold.progress.FixedTimingTransitionProgressProvider
import com.android.systemui.unfold.progress.PhysicsBasedUnfoldTransitionProgressProvider
import com.android.systemui.unfold.updates.DeviceFoldStateProvider
@@ -34,55 +32,18 @@
import dagger.Module
import dagger.Provides
import java.util.Optional
-import java.util.concurrent.Executor
+import javax.inject.Provider
import javax.inject.Singleton
-@Module
+@Module(includes = [UnfoldSharedInternalModule::class])
class UnfoldSharedModule {
@Provides
@Singleton
- fun unfoldTransitionProgressProvider(
- config: UnfoldTransitionConfig,
- scaleAwareProviderFactory: ScaleAwareTransitionProgressProvider.Factory,
- tracingListener: ATraceLoggerTransitionProgressListener,
- foldStateProvider: FoldStateProvider
- ): Optional<UnfoldTransitionProgressProvider> =
- if (!config.isEnabled) {
- Optional.empty()
- } else {
- val baseProgressProvider =
- if (config.isHingeAngleEnabled) {
- PhysicsBasedUnfoldTransitionProgressProvider(foldStateProvider)
- } else {
- FixedTimingTransitionProgressProvider(foldStateProvider)
- }
- Optional.of(
- scaleAwareProviderFactory.wrap(baseProgressProvider).apply {
- // Always present callback that logs animation beginning and end.
- addCallback(tracingListener)
- }
- )
- }
-
- @Provides
- @Singleton
fun provideFoldStateProvider(
deviceFoldStateProvider: DeviceFoldStateProvider
): FoldStateProvider = deviceFoldStateProvider
@Provides
- fun hingeAngleProvider(
- config: UnfoldTransitionConfig,
- sensorManager: SensorManager,
- @UnfoldBackground executor: Executor
- ): HingeAngleProvider =
- if (config.isHingeAngleEnabled) {
- HingeSensorAngleProvider(sensorManager, executor)
- } else {
- EmptyHingeAngleProvider
- }
-
- @Provides
@Singleton
fun unfoldKeyguardVisibilityProvider(
impl: UnfoldKeyguardVisibilityManagerImpl
@@ -94,3 +55,51 @@
impl: UnfoldKeyguardVisibilityManagerImpl
): UnfoldKeyguardVisibilityManager = impl
}
+
+/**
+ * Needed as methods inside must be public, but their parameters can be internal (and, a public
+ * method can't have internal parameters). Making the module internal and included in a public one
+ * fixes the issue.
+ */
+@Module
+internal class UnfoldSharedInternalModule {
+ @Provides
+ @Singleton
+ fun unfoldTransitionProgressProvider(
+ config: UnfoldTransitionConfig,
+ scaleAwareProviderFactory: ScaleAwareTransitionProgressProvider.Factory,
+ tracingListener: ATraceLoggerTransitionProgressListener,
+ physicsBasedUnfoldTransitionProgressProvider:
+ Provider<PhysicsBasedUnfoldTransitionProgressProvider>,
+ fixedTimingTransitionProgressProvider: Provider<FixedTimingTransitionProgressProvider>,
+ ): Optional<UnfoldTransitionProgressProvider> {
+ if (!config.isEnabled) {
+ return Optional.empty()
+ }
+ val baseProgressProvider =
+ if (config.isHingeAngleEnabled) {
+ physicsBasedUnfoldTransitionProgressProvider.get()
+ } else {
+ fixedTimingTransitionProgressProvider.get()
+ }
+
+ return Optional.of(
+ scaleAwareProviderFactory.wrap(baseProgressProvider).apply {
+ // Always present callback that logs animation beginning and end.
+ addCallback(tracingListener)
+ }
+ )
+ }
+
+ @Provides
+ fun hingeAngleProvider(
+ config: UnfoldTransitionConfig,
+ hingeAngleSensorProvider: Provider<HingeSensorAngleProvider>
+ ): HingeAngleProvider {
+ return if (config.isHingeAngleEnabled) {
+ hingeAngleSensorProvider.get()
+ } else {
+ EmptyHingeAngleProvider
+ }
+ }
+}
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt
index a1ed178..aa93c629 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt
@@ -37,29 +37,29 @@
* This should **never** be called from sysui, as the object is already provided in that process.
*/
fun createUnfoldSharedComponent(
- context: Context,
- config: UnfoldTransitionConfig,
- screenStatusProvider: ScreenStatusProvider,
- foldProvider: FoldProvider,
- activityTypeProvider: CurrentActivityTypeProvider,
- sensorManager: SensorManager,
- mainHandler: Handler,
- mainExecutor: Executor,
- backgroundExecutor: Executor,
- tracingTagPrefix: String,
- windowManager: IWindowManager,
+ context: Context,
+ config: UnfoldTransitionConfig,
+ screenStatusProvider: ScreenStatusProvider,
+ foldProvider: FoldProvider,
+ activityTypeProvider: CurrentActivityTypeProvider,
+ sensorManager: SensorManager,
+ mainHandler: Handler,
+ mainExecutor: Executor,
+ singleThreadBgExecutor: Executor,
+ tracingTagPrefix: String,
+ windowManager: IWindowManager,
): UnfoldSharedComponent =
- DaggerUnfoldSharedComponent.factory()
- .create(
- context,
- config,
- screenStatusProvider,
- foldProvider,
- activityTypeProvider,
- sensorManager,
- mainHandler,
- mainExecutor,
- backgroundExecutor,
- tracingTagPrefix,
- windowManager,
- )
+ DaggerUnfoldSharedComponent.factory()
+ .create(
+ context,
+ config,
+ screenStatusProvider,
+ foldProvider,
+ activityTypeProvider,
+ sensorManager,
+ mainHandler,
+ mainExecutor,
+ singleThreadBgExecutor,
+ tracingTagPrefix,
+ windowManager,
+ )
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/dagger/UnfoldBackground.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/dagger/UnfoldSingleThreadBg.kt
similarity index 89%
rename from packages/SystemUI/unfold/src/com/android/systemui/unfold/dagger/UnfoldBackground.kt
rename to packages/SystemUI/unfold/src/com/android/systemui/unfold/dagger/UnfoldSingleThreadBg.kt
index 6074795..dcac531 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/dagger/UnfoldBackground.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/dagger/UnfoldSingleThreadBg.kt
@@ -18,8 +18,7 @@
/**
* Alternative to [UiBackground] qualifier annotation in unfold module.
+ *
* It is needed as we can't depend on SystemUI code in this module.
*/
-@Qualifier
-@Retention(AnnotationRetention.RUNTIME)
-annotation class UnfoldBackground
+@Qualifier @Retention(AnnotationRetention.RUNTIME) annotation class UnfoldSingleThreadBg
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/FixedTimingTransitionProgressProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/FixedTimingTransitionProgressProvider.kt
index fa59cb4..4622464 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/FixedTimingTransitionProgressProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/FixedTimingTransitionProgressProvider.kt
@@ -24,11 +24,13 @@
import com.android.systemui.unfold.updates.FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE
import com.android.systemui.unfold.updates.FoldStateProvider
import com.android.systemui.unfold.updates.FoldStateProvider.FoldUpdate
+import javax.inject.Inject
/** Emits animation progress with fixed timing after unfolding */
-internal class FixedTimingTransitionProgressProvider(
- private val foldStateProvider: FoldStateProvider
-) : UnfoldTransitionProgressProvider, FoldStateProvider.FoldUpdatesListener {
+internal class FixedTimingTransitionProgressProvider
+@Inject
+constructor(private val foldStateProvider: FoldStateProvider) :
+ UnfoldTransitionProgressProvider, FoldStateProvider.FoldUpdatesListener {
private val animatorListener = AnimatorListener()
private val animator =
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
index 074b1e1..6ffbe5a 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
@@ -33,9 +33,10 @@
import com.android.systemui.unfold.updates.FoldStateProvider.FoldUpdate
import com.android.systemui.unfold.updates.FoldStateProvider.FoldUpdatesListener
import com.android.systemui.unfold.updates.name
+import javax.inject.Inject
/** Maps fold updates to unfold transition progress using DynamicAnimation. */
-class PhysicsBasedUnfoldTransitionProgressProvider(
+class PhysicsBasedUnfoldTransitionProgressProvider @Inject constructor(
private val foldStateProvider: FoldStateProvider
) : UnfoldTransitionProgressProvider, FoldUpdatesListener, DynamicAnimation.OnAnimationEndListener {
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/hinge/HingeSensorAngleProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/hinge/HingeSensorAngleProvider.kt
index 577137c..89fb12e 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/hinge/HingeSensorAngleProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/hinge/HingeSensorAngleProvider.kt
@@ -20,35 +20,43 @@
import android.hardware.SensorManager
import android.os.Trace
import androidx.core.util.Consumer
+import com.android.systemui.unfold.dagger.UnfoldSingleThreadBg
import java.util.concurrent.Executor
+import javax.inject.Inject
-internal class HingeSensorAngleProvider(
+internal class HingeSensorAngleProvider
+@Inject
+constructor(
private val sensorManager: SensorManager,
- private val executor: Executor
-) :
- HingeAngleProvider {
+ @UnfoldSingleThreadBg private val singleThreadBgExecutor: Executor
+) : HingeAngleProvider {
private val sensorListener = HingeAngleSensorListener()
private val listeners: MutableList<Consumer<Float>> = arrayListOf()
var started = false
- override fun start() = executor.execute {
- if (started) return@execute
- Trace.beginSection("HingeSensorAngleProvider#start")
- val sensor = sensorManager.getDefaultSensor(Sensor.TYPE_HINGE_ANGLE)
- sensorManager.registerListener(
- sensorListener,
- sensor,
- SensorManager.SENSOR_DELAY_FASTEST
- )
- Trace.endSection()
- started = true
+ override fun start() {
+ singleThreadBgExecutor.execute {
+ if (started) return@execute
+ Trace.beginSection("HingeSensorAngleProvider#start")
+ val sensor = sensorManager.getDefaultSensor(Sensor.TYPE_HINGE_ANGLE)
+ sensorManager.registerListener(
+ sensorListener,
+ sensor,
+ SensorManager.SENSOR_DELAY_FASTEST
+ )
+ Trace.endSection()
+
+ started = true
+ }
}
- override fun stop() = executor.execute {
- if (!started) return@execute
- sensorManager.unregisterListener(sensorListener)
- started = false
+ override fun stop() {
+ singleThreadBgExecutor.execute {
+ if (!started) return@execute
+ sensorManager.unregisterListener(sensorListener)
+ started = false
+ }
}
override fun removeCallback(listener: Consumer<Float>) {
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
index 05e305c..f4c6cc3 100644
--- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
@@ -132,7 +132,7 @@
private static final String TRACE_WM = "WindowManagerInternal";
private static final int WAIT_WINDOWS_TIMEOUT_MILLIS = 5000;
- /** Display type for displays associated with the default user of th device. */
+ /** Display type for displays associated with the default user of the device. */
public static final int DISPLAY_TYPE_DEFAULT = 1 << 0;
/** Display type for displays associated with an AccessibilityDisplayProxy user. */
public static final int DISPLAY_TYPE_PROXY = 1 << 1;
@@ -1993,17 +1993,29 @@
private int resolveAccessibilityWindowIdLocked(int accessibilityWindowId) {
if (accessibilityWindowId == AccessibilityWindowInfo.ACTIVE_WINDOW_ID) {
- return mA11yWindowManager.getActiveWindowId(mSystemSupport.getCurrentUserIdLocked());
+ final int focusedWindowId =
+ mA11yWindowManager.getActiveWindowId(mSystemSupport.getCurrentUserIdLocked());
+ if (!mA11yWindowManager.windowIdBelongsToDisplayType(focusedWindowId, mDisplayTypes)) {
+ return AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
+ }
+ return focusedWindowId;
}
return accessibilityWindowId;
}
private int resolveAccessibilityWindowIdForFindFocusLocked(int windowId, int focusType) {
- if (windowId == AccessibilityWindowInfo.ACTIVE_WINDOW_ID) {
- return mA11yWindowManager.getActiveWindowId(mSystemSupport.getCurrentUserIdLocked());
- }
if (windowId == AccessibilityWindowInfo.ANY_WINDOW_ID) {
- return mA11yWindowManager.getFocusedWindowId(focusType);
+ final int focusedWindowId = mA11yWindowManager.getFocusedWindowId(focusType);
+ // If the caller is a proxy and the found window doesn't belong to a proxy display
+ // (or vice versa), then return null. This doesn't work if there are multiple active
+ // proxys, but in the future this code shouldn't be needed if input and a11y focus are
+ // properly split. (so we will deal with the issues if we see them).
+ //TODO(254545943): Remove this when there is user and proxy separation of input and a11y
+ // focus
+ if (!mA11yWindowManager.windowIdBelongsToDisplayType(focusedWindowId, mDisplayTypes)) {
+ return AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
+ }
+ return focusedWindowId;
}
return windowId;
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 010189a..b28ab7a 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -3248,7 +3248,7 @@
if (targetName.equals(MAGNIFICATION_CONTROLLER_NAME)) {
final boolean enabled =
!getMagnificationController().getFullScreenMagnificationController()
- .isMagnifying(displayId);
+ .isActivated(displayId);
logAccessibilityShortcutActivated(mContext, MAGNIFICATION_COMPONENT_NAME, shortcutType,
enabled);
sendAccessibilityButtonToInputFilter(displayId);
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
index c050449e0..f0c6c4f 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
@@ -156,6 +156,30 @@
}
/**
+ * Returns {@code true} if the window belongs to a display of {@code displayTypes}.
+ */
+ public boolean windowIdBelongsToDisplayType(int focusedWindowId, int displayTypes) {
+ // UIAutomation wants focus from any display type.
+ final int displayTypeMask = DISPLAY_TYPE_PROXY | DISPLAY_TYPE_DEFAULT;
+ if ((displayTypes & displayTypeMask) == displayTypeMask) {
+ return true;
+ }
+ synchronized (mLock) {
+ final int count = mDisplayWindowsObservers.size();
+ for (int i = 0; i < count; i++) {
+ final DisplayWindowsObserver observer = mDisplayWindowsObservers.valueAt(i);
+ if (observer != null
+ && observer.findA11yWindowInfoByIdLocked(focusedWindowId) != null) {
+ return observer.mIsProxy
+ ? ((displayTypes & DISPLAY_TYPE_PROXY) != 0)
+ : (displayTypes & DISPLAY_TYPE_DEFAULT) != 0;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
* This class implements {@link WindowManagerInternal.WindowsForAccessibilityCallback} to
* receive {@link WindowInfo}s from window manager when there's an accessibility change in
* window and holds window lists information per display.
@@ -430,6 +454,7 @@
return;
}
windowInfo.title = attributes.getWindowTitle();
+ windowInfo.locales = attributes.getLocales();
}
private boolean shouldUpdateWindowsLocked(boolean forceSend,
@@ -756,6 +781,7 @@
reportedWindow.setPictureInPicture(window.inPictureInPicture);
reportedWindow.setDisplayId(window.displayId);
reportedWindow.setTaskId(window.taskId);
+ reportedWindow.setLocales(window.locales);
final int parentId = findWindowIdLocked(userId, window.parentToken);
if (parentId >= 0) {
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
index 6cfbfb8..de7184c 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
@@ -126,8 +126,6 @@
private boolean mUnregisterPending;
private boolean mDeleteAfterUnregister;
- private boolean mForceShowMagnifiableBounds;
-
private final int mDisplayId;
private int mIdOfLastServiceToMagnify = INVALID_SERVICE_ID;
@@ -213,8 +211,8 @@
return mRegistered;
}
- boolean isMagnifying() {
- return mCurrentMagnificationSpec.scale > 1.0f;
+ boolean isActivated() {
+ return mMagnificationActivated;
}
float getScale() {
@@ -370,12 +368,6 @@
@GuardedBy("mLock")
void onMagnificationChangedLocked() {
final float scale = getScale();
- final boolean lastMagnificationActivated = mMagnificationActivated;
- mMagnificationActivated = scale > 1.0f;
- if (mMagnificationActivated != lastMagnificationActivated) {
- mMagnificationInfoChangedCallback.onFullScreenMagnificationActivationState(
- mDisplayId, mMagnificationActivated);
- }
final MagnificationConfig config = new MagnificationConfig.Builder()
.setMode(MAGNIFICATION_MODE_FULLSCREEN)
@@ -384,7 +376,7 @@
.setCenterY(getCenterY()).build();
mMagnificationInfoChangedCallback.onFullScreenMagnificationChanged(mDisplayId,
mMagnificationRegion, config);
- if (mUnregisterPending && !isMagnifying()) {
+ if (mUnregisterPending && !isActivated()) {
unregister(mDeleteAfterUnregister);
}
}
@@ -476,21 +468,22 @@
}
@GuardedBy("mLock")
- void setForceShowMagnifiableBounds(boolean show) {
- if (mRegistered) {
- mForceShowMagnifiableBounds = show;
- if (traceEnabled()) {
- logTrace("setForceShowMagnifiableBounds",
- "displayID=" + mDisplayId + ";show=" + show);
- }
- mControllerCtx.getWindowManager().setForceShowMagnifiableBounds(
- mDisplayId, show);
+ private boolean setActivated(boolean activated) {
+ if (DEBUG) {
+ Slog.i(LOG_TAG, "setActivated(activated = " + activated + ")");
}
- }
- @GuardedBy("mLock")
- boolean isForceShowMagnifiableBounds() {
- return mRegistered && mForceShowMagnifiableBounds;
+ final boolean changed = (mMagnificationActivated != activated);
+
+ if (changed) {
+ mMagnificationActivated = activated;
+ mMagnificationInfoChangedCallback.onFullScreenMagnificationActivationState(
+ mDisplayId, mMagnificationActivated);
+ mControllerCtx.getWindowManager().setForceShowMagnifiableBounds(
+ mDisplayId, activated);
+ }
+
+ return changed;
}
@GuardedBy("mLock")
@@ -504,13 +497,13 @@
return false;
}
final MagnificationSpec spec = mCurrentMagnificationSpec;
- final boolean changed = !spec.isNop();
+ final boolean changed = isActivated();
+ setActivated(false);
if (changed) {
spec.clear();
onMagnificationChangedLocked();
}
mIdOfLastServiceToMagnify = INVALID_SERVICE_ID;
- mForceShowMagnifiableBounds = false;
sendSpecToAnimation(spec, animationCallback);
return changed;
}
@@ -554,9 +547,10 @@
+ ", centerY = " + centerY + ", endCallback = "
+ animationCallback + ", id = " + id + ")");
}
- final boolean changed = updateMagnificationSpecLocked(scale, centerX, centerY);
+ boolean changed = setActivated(true);
+ changed |= updateMagnificationSpecLocked(scale, centerX, centerY);
sendSpecToAnimation(mCurrentMagnificationSpec, animationCallback);
- if (isMagnifying() && (id != INVALID_SERVICE_ID)) {
+ if (isActivated() && (id != INVALID_SERVICE_ID)) {
mIdOfLastServiceToMagnify = id;
mMagnificationInfoChangedCallback.onRequestMagnificationSpec(mDisplayId,
mIdOfLastServiceToMagnify);
@@ -779,7 +773,7 @@
if (display == null) {
return;
}
- if (!display.isMagnifying()) {
+ if (!display.isActivated()) {
return;
}
final Rect magnifiedRegionBounds = mTempRect;
@@ -831,16 +825,16 @@
/**
* @param displayId The logical display id.
- * @return {@code true} if magnification is active, e.g. the scale
- * is > 1, {@code false} otherwise
+ * @return {@code true} if magnification is activated,
+ * {@code false} otherwise
*/
- public boolean isMagnifying(int displayId) {
+ public boolean isActivated(int displayId) {
synchronized (mLock) {
final DisplayMagnification display = mDisplays.get(displayId);
if (display == null) {
return false;
}
- return display.isMagnifying();
+ return display.isActivated();
}
}
@@ -1166,6 +1160,9 @@
*/
public void persistScale(int displayId) {
final float scale = getScale(Display.DEFAULT_DISPLAY);
+ if (scale < 2.0f) {
+ return;
+ }
mScaleProvider.putScale(scale, displayId);
}
@@ -1177,7 +1174,8 @@
* scale if none is available
*/
public float getPersistedScale(int displayId) {
- return mScaleProvider.getScale(displayId);
+ return MathUtils.constrain(mScaleProvider.getScale(displayId),
+ 2.0f, MagnificationScaleProvider.MAX_SCALE);
}
/**
@@ -1198,12 +1196,12 @@
*
* @param displayId The logical display id.
* @param animate whether the animate the transition
- * @return whether was {@link #isMagnifying(int) magnifying}
+ * @return whether was {@link #isActivated(int)} activated}
*/
boolean resetIfNeeded(int displayId, boolean animate) {
synchronized (mLock) {
final DisplayMagnification display = mDisplays.get(displayId);
- if (display == null || !display.isMagnifying()) {
+ if (display == null || !display.isActivated()) {
return false;
}
display.reset(animate);
@@ -1221,7 +1219,7 @@
boolean resetIfNeeded(int displayId, int connectionId) {
synchronized (mLock) {
final DisplayMagnification display = mDisplays.get(displayId);
- if (display == null || !display.isMagnifying()
+ if (display == null || !display.isActivated()
|| connectionId != display.getIdOfLastServiceToMagnify()) {
return false;
}
@@ -1230,16 +1228,6 @@
}
}
- void setForceShowMagnifiableBounds(int displayId, boolean show) {
- synchronized (mLock) {
- final DisplayMagnification display = mDisplays.get(displayId);
- if (display == null) {
- return;
- }
- display.setForceShowMagnifiableBounds(show);
- }
- }
-
/**
* Notifies that the IME window visibility changed.
*
@@ -1251,21 +1239,6 @@
mMagnificationInfoChangedCallback.onImeWindowVisibilityChanged(displayId, shown);
}
- /**
- * Returns {@code true} if the magnifiable regions of the display is forced to be shown.
- *
- * @param displayId The logical display id.
- */
- public boolean isForceShowMagnifiableBounds(int displayId) {
- synchronized (mLock) {
- final DisplayMagnification display = mDisplays.get(displayId);
- if (display == null) {
- return false;
- }
- return display.isForceShowMagnifiableBounds();
- }
- }
-
private void onScreenTurnedOff() {
final Message m = PooledLambda.obtainMessage(
FullScreenMagnificationController::resetAllIfNeeded, this, false);
@@ -1295,7 +1268,7 @@
}
return;
}
- if (!display.isMagnifying()) {
+ if (!display.isActivated()) {
display.unregister(delete);
} else {
display.unregisterPending(delete);
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
index dc39b01..6bf37a1 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
@@ -122,7 +122,7 @@
// The MIN_SCALE is different from MagnificationScaleProvider.MIN_SCALE due
// to AccessibilityService.MagnificationController#setScale() has
// different scale range
- private static final float MIN_SCALE = 2.0f;
+ private static final float MIN_SCALE = 1.0f;
private static final float MAX_SCALE = MagnificationScaleProvider.MAX_SCALE;
@VisibleForTesting final FullScreenMagnificationController mFullScreenMagnificationController;
@@ -220,14 +220,19 @@
@Override
public void handleShortcutTriggered() {
- boolean wasMagnifying = mFullScreenMagnificationController.resetIfNeeded(mDisplayId,
- /* animate */ true);
- if (wasMagnifying) {
+ final boolean isActivated = mFullScreenMagnificationController.isActivated(mDisplayId);
+
+ if (isActivated) {
+ zoomOff();
clearAndTransitionToStateDetecting();
} else {
- mPromptController.showNotificationIfNeeded();
mDetectingState.toggleShortcutTriggered();
}
+
+ if (mDetectingState.isShortcutTriggered()) {
+ mPromptController.showNotificationIfNeeded();
+ zoomToScale(1.0f, Float.NaN, Float.NaN);
+ }
}
@Override
@@ -441,7 +446,12 @@
final class ViewportDraggingState implements State {
/** Whether to disable zoom after dragging ends */
- boolean mZoomedInBeforeDrag;
+ @VisibleForTesting boolean mActivatedBeforeDrag;
+ /** Whether to restore scale after dragging ends */
+ private boolean mZoomedInTemporary;
+ /** The cached scale for recovering after dragging ends */
+ private float mScaleBeforeZoomedInTemporary;
+
private boolean mLastMoveOutsideMagnifiedRegion;
@Override
@@ -474,7 +484,13 @@
case ACTION_UP:
case ACTION_CANCEL: {
- if (!mZoomedInBeforeDrag) zoomOff();
+ if (mActivatedBeforeDrag) {
+ if (mZoomedInTemporary) {
+ zoomToScale(mScaleBeforeZoomedInTemporary, event.getX(), event.getY());
+ }
+ } else {
+ zoomOff();
+ }
clear();
transitionTo(mDetectingState);
}
@@ -488,15 +504,27 @@
}
}
+ public void prepareForZoomInTemporary() {
+ mViewportDraggingState.mActivatedBeforeDrag =
+ mFullScreenMagnificationController.isActivated(mDisplayId);
+
+ mViewportDraggingState.mZoomedInTemporary = true;
+ mViewportDraggingState.mScaleBeforeZoomedInTemporary =
+ mFullScreenMagnificationController.getScale(mDisplayId);
+ }
+
@Override
public void clear() {
mLastMoveOutsideMagnifiedRegion = false;
+
+ mZoomedInTemporary = false;
+ mScaleBeforeZoomedInTemporary = 1.0f;
}
@Override
public String toString() {
return "ViewportDraggingState{"
- + "mZoomedInBeforeDrag=" + mZoomedInBeforeDrag
+ + "mActivatedBeforeDrag=" + mActivatedBeforeDrag
+ ", mLastMoveOutsideMagnifiedRegion=" + mLastMoveOutsideMagnifiedRegion
+ '}';
}
@@ -625,10 +653,10 @@
transitionToDelegatingStateAndClear();
} else if (mDetectTripleTap
- // If magnified, delay an ACTION_DOWN for mMultiTapMaxDelay
+ // If activated, delay an ACTION_DOWN for mMultiTapMaxDelay
// to ensure reachability of
// STATE_PANNING_SCALING(triggerable with ACTION_POINTER_DOWN)
- || mFullScreenMagnificationController.isMagnifying(mDisplayId)) {
+ || isActivated()) {
afterMultiTapTimeoutTransitionToDelegatingState();
@@ -640,8 +668,7 @@
}
break;
case ACTION_POINTER_DOWN: {
- if (mFullScreenMagnificationController.isMagnifying(mDisplayId)
- && event.getPointerCount() == 2) {
+ if (isActivated() && event.getPointerCount() == 2) {
storeSecondPointerDownLocation(event);
mHandler.sendEmptyMessageDelayed(MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE,
ViewConfiguration.getTapTimeout());
@@ -665,13 +692,13 @@
// (which is a rare combo to be used aside from magnification)
if (isMultiTapTriggered(2 /* taps */) && event.getPointerCount() == 1) {
transitionToViewportDraggingStateAndClear(event);
- } else if (isMagnifying() && event.getPointerCount() == 2) {
+ } else if (isActivated() && event.getPointerCount() == 2) {
//Primary pointer is swiping, so transit to PanningScalingState
transitToPanningScalingStateAndClear();
} else {
transitionToDelegatingStateAndClear();
}
- } else if (isMagnifying() && secondPointerDownValid()
+ } else if (isActivated() && secondPointerDownValid()
&& distanceClosestPointerToPoint(
mSecondPointerDownLocation, /* move */ event) > mSwipeMinDistance) {
//Second pointer is swiping, so transit to PanningScalingState
@@ -734,7 +761,7 @@
// Only log the triple tap event, use numTaps to filter.
if (multitapTriggered && numTaps > 2) {
- final boolean enabled = mFullScreenMagnificationController.isMagnifying(mDisplayId);
+ final boolean enabled = isActivated();
logMagnificationTripleTap(enabled);
}
return multitapTriggered;
@@ -862,24 +889,33 @@
mSecondPointerDownLocation.set(Float.NaN, Float.NaN);
}
+ /**
+ * This method could be triggered by both 2 cases.
+ * 1. direct three tap gesture
+ * 2. one tap while shortcut triggered (it counts as two taps).
+ */
private void onTripleTap(MotionEvent up) {
if (DEBUG_DETECTING) {
Slog.i(mLogTag, "onTripleTap(); delayed: "
+ MotionEventInfo.toString(mDelayedEventQueue));
}
- clear();
- // Toggle zoom
- if (mFullScreenMagnificationController.isMagnifying(mDisplayId)) {
- zoomOff();
- } else {
+ // We put mShortcutTriggered into conditions.
+ // The reason is when the shortcut is triggered,
+ // the magnifier is activated and keeps in scale 1.0,
+ // and in this case, we still want to zoom on the magnifier.
+ if (!isActivated() || mShortcutTriggered) {
mPromptController.showNotificationIfNeeded();
zoomOn(up.getX(), up.getY());
+ } else {
+ zoomOff();
}
+
+ clear();
}
- private boolean isMagnifying() {
- return mFullScreenMagnificationController.isMagnifying(mDisplayId);
+ private boolean isActivated() {
+ return mFullScreenMagnificationController.isActivated(mDisplayId);
}
void transitionToViewportDraggingStateAndClear(MotionEvent down) {
@@ -887,14 +923,13 @@
if (DEBUG_DETECTING) Slog.i(mLogTag, "onTripleTapAndHold()");
clear();
- mViewportDraggingState.mZoomedInBeforeDrag =
- mFullScreenMagnificationController.isMagnifying(mDisplayId);
-
// Triple tap and hold also belongs to triple tap event.
- final boolean enabled = !mViewportDraggingState.mZoomedInBeforeDrag;
+ final boolean enabled = !isActivated();
logMagnificationTripleTap(enabled);
- zoomOn(down.getX(), down.getY());
+ mViewportDraggingState.prepareForZoomInTemporary();
+
+ zoomInTemporary(down.getX(), down.getY());
transitionTo(mViewportDraggingState);
}
@@ -919,7 +954,10 @@
if (DEBUG_DETECTING) Slog.i(mLogTag, "setShortcutTriggered(" + state + ")");
mShortcutTriggered = state;
- mFullScreenMagnificationController.setForceShowMagnifiableBounds(mDisplayId, state);
+ }
+
+ private boolean isShortcutTriggered() {
+ return mShortcutTriggered;
}
/**
@@ -948,12 +986,29 @@
}
}
+ private void zoomInTemporary(float centerX, float centerY) {
+ final float currentScale = mFullScreenMagnificationController.getScale(mDisplayId);
+ final float persistedScale = MathUtils.constrain(
+ mFullScreenMagnificationController.getPersistedScale(mDisplayId),
+ MIN_SCALE, MAX_SCALE);
+
+ final float scale = MathUtils.constrain(Math.max(currentScale + 1.0f, persistedScale),
+ MIN_SCALE, MAX_SCALE);
+
+ zoomToScale(scale, centerX, centerY);
+ }
+
private void zoomOn(float centerX, float centerY) {
if (DEBUG_DETECTING) Slog.i(mLogTag, "zoomOn(" + centerX + ", " + centerY + ")");
final float scale = MathUtils.constrain(
mFullScreenMagnificationController.getPersistedScale(mDisplayId),
MIN_SCALE, MAX_SCALE);
+ zoomToScale(scale, centerX, centerY);
+ }
+
+ private void zoomToScale(float scale, float centerX, float centerY) {
+ scale = MathUtils.constrain(scale, MIN_SCALE, MAX_SCALE);
mFullScreenMagnificationController.setScaleAndCenter(mDisplayId,
scale, centerX, centerY,
/* animate */ true,
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java
index 02e810f..129bc16 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java
@@ -254,13 +254,15 @@
final DisableMagnificationCallback animationEndCallback =
new DisableMagnificationCallback(transitionCallBack, displayId, targetMode,
scale, currentCenter, true);
+
+ setDisableMagnificationCallbackLocked(displayId, animationEndCallback);
+
if (targetMode == ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW) {
screenMagnificationController.reset(displayId, animationEndCallback);
} else {
windowMagnificationMgr.disableWindowMagnification(displayId, false,
animationEndCallback);
}
- setDisableMagnificationCallbackLocked(displayId, animationEndCallback);
}
/**
@@ -481,17 +483,17 @@
*/
private boolean shouldNotifyMagnificationChange(int displayId, int changeMode) {
synchronized (mLock) {
- final boolean fullScreenMagnifying = mFullScreenMagnificationController != null
- && mFullScreenMagnificationController.isMagnifying(displayId);
+ final boolean fullScreenActivated = mFullScreenMagnificationController != null
+ && mFullScreenMagnificationController.isActivated(displayId);
final boolean windowEnabled = mWindowMagnificationMgr != null
&& mWindowMagnificationMgr.isWindowMagnifierEnabled(displayId);
final Integer transitionMode = mTransitionModes.get(displayId);
- if (((changeMode == MAGNIFICATION_MODE_FULLSCREEN && fullScreenMagnifying)
+ if (((changeMode == MAGNIFICATION_MODE_FULLSCREEN && fullScreenActivated)
|| (changeMode == MAGNIFICATION_MODE_WINDOW && windowEnabled))
&& (transitionMode == null)) {
return true;
}
- if ((!fullScreenMagnifying && !windowEnabled)
+ if ((!fullScreenActivated && !windowEnabled)
&& (transitionMode == null)) {
return true;
}
@@ -742,7 +744,7 @@
mWindowMagnificationMgr.getCenterY(displayId));
} else {
if (mFullScreenMagnificationController == null
- || !mFullScreenMagnificationController.isMagnifying(displayId)) {
+ || !mFullScreenMagnificationController.isActivated(displayId)) {
return null;
}
mTempPoint.set(mFullScreenMagnificationController.getCenterX(displayId),
@@ -766,9 +768,7 @@
if (mFullScreenMagnificationController == null) {
return false;
}
- isActivated = mFullScreenMagnificationController.isMagnifying(displayId)
- || mFullScreenMagnificationController.isForceShowMagnifiableBounds(
- displayId);
+ isActivated = mFullScreenMagnificationController.isActivated(displayId);
}
} else if (mode == ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW) {
synchronized (mLock) {
@@ -829,7 +829,7 @@
final FullScreenMagnificationController screenMagnificationController =
getFullScreenMagnificationController();
if (mCurrentMode == ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN
- && !screenMagnificationController.isMagnifying(mDisplayId)) {
+ && !screenMagnificationController.isActivated(mDisplayId)) {
MagnificationConfig.Builder configBuilder =
new MagnificationConfig.Builder();
Region region = new Region();
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationProcessor.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationProcessor.java
index a356ae6..75fe026 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationProcessor.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationProcessor.java
@@ -313,13 +313,13 @@
}
/**
- * {@link FullScreenMagnificationController#isMagnifying(int)}
+ * {@link FullScreenMagnificationController#isActivated(int)}
* {@link WindowMagnificationManager#isWindowMagnifierEnabled(int)}
*/
public boolean isMagnifying(int displayId) {
int mode = getControllingMode(displayId);
if (mode == MAGNIFICATION_MODE_FULLSCREEN) {
- return mController.getFullScreenMagnificationController().isMagnifying(displayId);
+ return mController.getFullScreenMagnificationController().isActivated(displayId);
} else if (mode == MAGNIFICATION_MODE_WINDOW) {
return mController.getWindowMagnificationMgr().isWindowMagnifierEnabled(displayId);
}
diff --git a/services/api/current.txt b/services/api/current.txt
index aab6a6c..3926b39 100644
--- a/services/api/current.txt
+++ b/services/api/current.txt
@@ -38,7 +38,8 @@
package com.android.server.am {
public interface ActivityManagerLocal {
- method public boolean bindSdkSandboxService(@NonNull android.content.Intent, @NonNull android.content.ServiceConnection, int, @NonNull String, @NonNull String, int) throws android.os.RemoteException;
+ method public boolean bindSdkSandboxService(@NonNull android.content.Intent, @NonNull android.content.ServiceConnection, int, @NonNull android.os.IBinder, @NonNull String, @NonNull String, int) throws android.os.RemoteException;
+ method @Deprecated public boolean bindSdkSandboxService(@NonNull android.content.Intent, @NonNull android.content.ServiceConnection, int, @NonNull String, @NonNull String, int) throws android.os.RemoteException;
method public boolean canStartForegroundService(int, int, @NonNull String);
method public void killSdkSandboxClientAppProcess(@NonNull android.os.IBinder);
}
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index 54f77b1..6b61e97 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -67,6 +67,7 @@
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.TimeUtils;
+import android.view.autofill.AutofillFeatureFlags;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillManager;
import android.view.autofill.AutofillManager.AutofillCommitReason;
@@ -298,12 +299,12 @@
private void onDeviceConfigChange(@NonNull Set<String> keys) {
for (String key : keys) {
switch (key) {
- case AutofillManager.DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES:
- case AutofillManager.DEVICE_CONFIG_AUGMENTED_SERVICE_IDLE_UNBIND_TIMEOUT:
- case AutofillManager.DEVICE_CONFIG_AUGMENTED_SERVICE_REQUEST_TIMEOUT:
+ case AutofillFeatureFlags.DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES:
+ case AutofillFeatureFlags.DEVICE_CONFIG_AUGMENTED_SERVICE_IDLE_UNBIND_TIMEOUT:
+ case AutofillFeatureFlags.DEVICE_CONFIG_AUGMENTED_SERVICE_REQUEST_TIMEOUT:
setDeviceConfigProperties();
break;
- case AutofillManager.DEVICE_CONFIG_AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES:
+ case AutofillFeatureFlags.DEVICE_CONFIG_AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES:
updateCachedServices();
break;
default:
@@ -567,15 +568,15 @@
synchronized (mLock) {
mAugmentedServiceIdleUnbindTimeoutMs = DeviceConfig.getInt(
DeviceConfig.NAMESPACE_AUTOFILL,
- AutofillManager.DEVICE_CONFIG_AUGMENTED_SERVICE_IDLE_UNBIND_TIMEOUT,
+ AutofillFeatureFlags.DEVICE_CONFIG_AUGMENTED_SERVICE_IDLE_UNBIND_TIMEOUT,
(int) AbstractRemoteService.PERMANENT_BOUND_TIMEOUT_MS);
mAugmentedServiceRequestTimeoutMs = DeviceConfig.getInt(
DeviceConfig.NAMESPACE_AUTOFILL,
- AutofillManager.DEVICE_CONFIG_AUGMENTED_SERVICE_REQUEST_TIMEOUT,
+ AutofillFeatureFlags.DEVICE_CONFIG_AUGMENTED_SERVICE_REQUEST_TIMEOUT,
DEFAULT_AUGMENTED_AUTOFILL_REQUEST_TIMEOUT_MILLIS);
mSupportedSmartSuggestionModes = DeviceConfig.getInt(
DeviceConfig.NAMESPACE_AUTOFILL,
- AutofillManager.DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES,
+ AutofillFeatureFlags.DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES,
AutofillManager.FLAG_SMART_SUGGESTION_SYSTEM);
if (verbose) {
Slog.v(mTag, "setDeviceConfigProperties(): "
@@ -729,7 +730,7 @@
private String getAllowedCompatModePackagesFromDeviceConfig() {
String config = DeviceConfig.getString(
DeviceConfig.NAMESPACE_AUTOFILL,
- AutofillManager.DEVICE_CONFIG_AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES,
+ AutofillFeatureFlags.DEVICE_CONFIG_AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES,
/* defaultValue */ null);
if (!TextUtils.isEmpty(config)) {
return config;
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 81fbd78..939047f 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -2651,8 +2651,8 @@
final CharSequence serviceLabel;
final Drawable serviceIcon;
synchronized (mLock) {
- serviceLabel = mService.getServiceLabelLocked();
- serviceIcon = mService.getServiceIconLocked();
+ serviceIcon = getServiceIcon(response);
+ serviceLabel = getServiceLabel(response);
}
if (serviceLabel == null || serviceIcon == null) {
wtf(null, "showSaveLocked(): no service label or icon");
@@ -2662,7 +2662,8 @@
getUiForShowing().showSaveUi(serviceLabel, serviceIcon,
mService.getServicePackageName(), saveInfo, this,
- mComponentName, this, mPendingSaveUi, isUpdate, mCompatMode);
+ mComponentName, this, mPendingSaveUi, isUpdate, mCompatMode,
+ response.getShowSaveDialogIcon());
if (client != null) {
try {
client.setSaveUiState(id, true);
@@ -3600,9 +3601,13 @@
if (sDebug) Log.w(TAG, "Last fill dialog triggered ids are changed.");
return false;
}
+
}
- final Drawable serviceIcon = getServiceIcon();
+ Drawable serviceIcon = null;
+ synchronized (mLock) {
+ serviceIcon = getServiceIcon(response);
+ }
getUiForShowing().showFillDialog(filledId, response, filterText,
mService.getServicePackageName(), mComponentName, serviceIcon, this,
@@ -3610,13 +3615,64 @@
return true;
}
+ /**
+ * Get the custom icon that was passed through FillResponse. If the custom icon wasn't able
+ * to be fetched, use the default provider icon instead
+ *
+ * @return Drawable of the provider icon, if it was able to be fetched. Null otherwise
+ */
@SuppressWarnings("GuardedBy") // ErrorProne says we need to use mService.mLock, but it's
// actually the same object as mLock.
// TODO: Expose mService.mLock or redesign instead.
- private Drawable getServiceIcon() {
- synchronized (mLock) {
- return mService.getServiceIconLocked();
+ @GuardedBy("mLock")
+ private Drawable getServiceIcon(FillResponse response) {
+ Drawable serviceIcon = null;
+ // Try to get the custom Icon, if one was passed through FillResponse
+ int iconResourceId = response.getIconResourceId();
+ if (iconResourceId != 0) {
+ serviceIcon = mService.getMaster().getContext().getPackageManager()
+ .getDrawable(
+ mService.getServicePackageName(),
+ iconResourceId,
+ null);
}
+
+ // Custom icon wasn't fetched, use the default package icon instead
+ if (serviceIcon == null) {
+ serviceIcon = mService.getServiceIconLocked();
+ }
+
+ return serviceIcon;
+ }
+
+ /**
+ * Get the custom label that was passed through FillResponse. If the custom label
+ * wasn't able to be fetched, use the default provider icon instead
+ *
+ * @return Drawable of the provider icon, if it was able to be fetched. Null otherwise
+ */
+ @SuppressWarnings("GuardedBy") // ErrorProne says we need to use mService.mLock, but it's
+ // actually the same object as mLock.
+ // TODO: Expose mService.mLock or redesign instead.
+ @GuardedBy("mLock")
+ private CharSequence getServiceLabel(FillResponse response) {
+ CharSequence serviceLabel = null;
+ // Try to get the custom Service name, if one was passed through FillResponse
+ int customServiceNameId = response.getServiceDisplayNameResourceId();
+ if (customServiceNameId != 0) {
+ serviceLabel = mService.getMaster().getContext().getPackageManager()
+ .getText(
+ mService.getServicePackageName(),
+ customServiceNameId,
+ null);
+ }
+
+ // Custom label wasn't fetched, use the default package name instead
+ if (serviceLabel == null) {
+ serviceLabel = mService.getServiceLabelLocked();
+ }
+
+ return serviceLabel;
}
/**
diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
index 5f0f9a3..7db6e6f 100644
--- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -315,7 +315,7 @@
@Nullable String servicePackageName, @NonNull SaveInfo info,
@NonNull ValueFinder valueFinder, @NonNull ComponentName componentName,
@NonNull AutoFillUiCallback callback, @NonNull PendingUi pendingSaveUi,
- boolean isUpdate, boolean compatMode) {
+ boolean isUpdate, boolean compatMode, boolean showServiceIcon) {
if (sVerbose) {
Slog.v(TAG, "showSaveUi(update=" + isUpdate + ") for " + componentName.toShortString()
+ ": " + info);
@@ -379,7 +379,7 @@
public void startIntentSender(IntentSender intentSender, Intent intent) {
callback.startIntentSender(intentSender, intent);
}
- }, mUiModeMgr.isNightMode(), isUpdate, compatMode);
+ }, mUiModeMgr.isNightMode(), isUpdate, compatMode, showServiceIcon);
});
}
diff --git a/services/autofill/java/com/android/server/autofill/ui/DialogFillUi.java b/services/autofill/java/com/android/server/autofill/ui/DialogFillUi.java
index c2c630e..72a38eb 100644
--- a/services/autofill/java/com/android/server/autofill/ui/DialogFillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/DialogFillUi.java
@@ -117,7 +117,9 @@
final LayoutInflater inflater = LayoutInflater.from(mContext);
final View decor = inflater.inflate(R.layout.autofill_fill_dialog, null);
- setServiceIcon(decor, serviceIcon);
+ if (response.getShowFillDialogIcon()) {
+ setServiceIcon(decor, serviceIcon);
+ }
setHeader(decor, response);
mVisibleDatasetsMaxCount = getVisibleDatasetsMaxCount();
diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
index 8c2c964..7db27ac 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -177,7 +177,7 @@
@Nullable String servicePackageName, @NonNull ComponentName componentName,
@NonNull SaveInfo info, @NonNull ValueFinder valueFinder,
@NonNull OverlayControl overlayControl, @NonNull OnSaveListener listener,
- boolean nightMode, boolean isUpdate, boolean compatMode) {
+ boolean nightMode, boolean isUpdate, boolean compatMode, boolean showServiceIcon) {
if (sVerbose) Slog.v(TAG, "nightMode: " + nightMode);
mThemeId = nightMode ? THEME_ID_DARK : THEME_ID_LIGHT;
mPendingUi = pendingUi;
@@ -288,7 +288,9 @@
}
titleView.setText(mTitle);
- setServiceIcon(context, view, serviceIcon);
+ if (showServiceIcon) {
+ setServiceIcon(context, view, serviceIcon);
+ }
final boolean hasCustomDescription =
applyCustomDescription(context, view, valueFinder, info);
diff --git a/services/backup/java/com/android/server/backup/TransportManager.java b/services/backup/java/com/android/server/backup/TransportManager.java
index a4ea698..05327dc 100644
--- a/services/backup/java/com/android/server/backup/TransportManager.java
+++ b/services/backup/java/com/android/server/backup/TransportManager.java
@@ -156,14 +156,16 @@
} catch (IllegalArgumentException ex) {
// packageName doesn't exist: likely due to a race with it being uninstalled.
if (MORE_DEBUG) {
- Slog.d(TAG, "Package " + packageName + " was changed, but no longer exists.");
+ Slog.d(TAG, addUserIdToLogMessage(mUserId, "Package " + packageName
+ + " was changed, but no longer exists."));
}
return;
}
switch (enabled) {
case COMPONENT_ENABLED_STATE_ENABLED: {
if (MORE_DEBUG) {
- Slog.d(TAG, "Package " + packageName + " was enabled.");
+ Slog.d(TAG, addUserIdToLogMessage(mUserId, "Package " + packageName
+ + " was enabled."));
}
onPackageEnabled(packageName);
return;
@@ -173,28 +175,31 @@
// Unless explicitly specified in manifest, the default enabled state
// is 'enabled'. Here, we assume that default state always means enabled.
if (MORE_DEBUG) {
- Slog.d(TAG, "Package " + packageName
- + " was put in default enabled state.");
+ Slog.d(TAG, addUserIdToLogMessage(mUserId, "Package " + packageName
+ + " was put in default enabled state."));
}
onPackageEnabled(packageName);
return;
}
case COMPONENT_ENABLED_STATE_DISABLED: {
if (MORE_DEBUG) {
- Slog.d(TAG, "Package " + packageName + " was disabled.");
+ Slog.d(TAG, addUserIdToLogMessage(mUserId, "Package " + packageName
+ + " was disabled."));
}
onPackageDisabled(packageName);
return;
}
case COMPONENT_ENABLED_STATE_DISABLED_USER: {
if (MORE_DEBUG) {
- Slog.d(TAG, "Package " + packageName + " was disabled by user.");
+ Slog.d(TAG, addUserIdToLogMessage(mUserId, "Package " + packageName
+ + " was disabled by user."));
}
onPackageDisabled(packageName);
return;
}
default: {
- Slog.w(TAG, "Package " + packageName + " enabled setting: " + enabled);
+ Slog.w(TAG, addUserIdToLogMessage(mUserId, "Package " + packageName
+ + " enabled setting: " + enabled));
return;
}
}
@@ -405,7 +410,8 @@
TransportDescription description =
mRegisteredTransportsDescriptionMap.get(transportComponent);
if (description == null) {
- Slog.e(TAG, "Transport " + name + " not registered tried to change description");
+ Slog.e(TAG, addUserIdToLogMessage(mUserId, "Transport " + name
+ + " not registered tried to change description"));
return;
}
description.name = name;
@@ -413,7 +419,8 @@
description.currentDestinationString = currentDestinationString;
description.dataManagementIntent = dataManagementIntent;
description.dataManagementLabel = dataManagementLabel;
- Slog.d(TAG, "Transport " + name + " updated its attributes");
+ Slog.d(TAG, addUserIdToLogMessage(mUserId, "Transport " + name
+ + " updated its attributes"));
}
}
@@ -493,7 +500,8 @@
try {
return getTransportClientOrThrow(transportName, caller);
} catch (TransportNotRegisteredException e) {
- Slog.w(TAG, "Transport " + transportName + " not registered");
+ Slog.w(TAG, addUserIdToLogMessage(mUserId, "Transport " + transportName
+ + " not registered"));
return null;
}
}
@@ -620,7 +628,7 @@
selectTransport(getTransportName(transportComponent));
return BackupManager.SUCCESS;
} catch (TransportNotRegisteredException e) {
- Slog.wtf(TAG, "Transport got unregistered");
+ Slog.wtf(TAG, addUserIdToLogMessage(mUserId, "Transport got unregistered"));
return BackupManager.ERROR_TRANSPORT_UNAVAILABLE;
}
}
@@ -637,7 +645,8 @@
try {
mPackageManager.getPackageInfoAsUser(packageName, 0, mUserId);
} catch (PackageManager.NameNotFoundException e) {
- Slog.e(TAG, "Trying to register transports from package not found " + packageName);
+ Slog.e(TAG, addUserIdToLogMessage(mUserId,
+ "Trying to register transports from package not found " + packageName));
return;
}
@@ -668,7 +677,8 @@
if (!mTransportWhitelist.contains(transport)) {
Slog.w(
TAG,
- "BackupTransport " + transport.flattenToShortString() + " not whitelisted.");
+ addUserIdToLogMessage(mUserId, "BackupTransport "
+ + transport.flattenToShortString() + " not whitelisted."));
return false;
}
try {
@@ -676,11 +686,12 @@
mPackageManager.getPackageInfoAsUser(transport.getPackageName(), 0, mUserId);
if ((packInfo.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED)
== 0) {
- Slog.w(TAG, "Transport package " + transport.getPackageName() + " not privileged");
+ Slog.w(TAG, addUserIdToLogMessage(mUserId, "Transport package "
+ + transport.getPackageName() + " not privileged"));
return false;
}
} catch (PackageManager.NameNotFoundException e) {
- Slog.w(TAG, "Package not found.", e);
+ Slog.w(TAG, addUserIdToLogMessage(mUserId, "Package not found."), e);
return false;
}
return true;
@@ -716,7 +727,8 @@
try {
transport = transportConnection.connectOrThrow(callerLogString);
} catch (TransportNotAvailableException e) {
- Slog.e(TAG, "Couldn't connect to transport " + transportString + " for registration");
+ Slog.e(TAG, addUserIdToLogMessage(mUserId, "Couldn't connect to transport "
+ + transportString + " for registration"));
mTransportConnectionManager.disposeOfTransportClient(transportConnection,
callerLogString);
return BackupManager.ERROR_TRANSPORT_UNAVAILABLE;
@@ -728,11 +740,13 @@
String transportDirName = transport.transportDirName();
registerTransport(transportComponent, transport);
// If registerTransport() hasn't thrown...
- Slog.d(TAG, "Transport " + transportString + " registered");
+ Slog.d(TAG, addUserIdToLogMessage(mUserId, "Transport " + transportString
+ + " registered"));
mOnTransportRegisteredListener.onTransportRegistered(transportName, transportDirName);
result = BackupManager.SUCCESS;
} catch (RemoteException e) {
- Slog.e(TAG, "Transport " + transportString + " died while registering");
+ Slog.e(TAG, addUserIdToLogMessage(mUserId, "Transport " + transportString
+ + " died while registering"));
result = BackupManager.ERROR_TRANSPORT_UNAVAILABLE;
}
@@ -798,4 +812,8 @@
this.dataManagementLabel = dataManagementLabel;
}
}
+
+ private static String addUserIdToLogMessage(int userId, String message) {
+ return "[UserID:" + userId + "] " + message;
+ }
}
diff --git a/services/companion/java/com/android/server/companion/virtual/TEST_MAPPING b/services/companion/java/com/android/server/companion/virtual/TEST_MAPPING
new file mode 100644
index 0000000..279981b
--- /dev/null
+++ b/services/companion/java/com/android/server/companion/virtual/TEST_MAPPING
@@ -0,0 +1,24 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsVirtualDevicesTestCases",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ },
+ {
+ "name": "CtsVirtualDevicesTestCases",
+ "options": [
+ {
+ "include-filter": "android.hardware.input.cts.tests"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ],
+ "file_patterns": ["Virtual[^/]*\\.java"]
+ }
+ ]
+}
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 17b6f5d..97e9d26 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -101,6 +101,8 @@
defaults: ["platform_service_defaults"],
srcs: [
":android.hardware.biometrics.face-V3-java-source",
+ ":android.hardware.tv.hdmi.connection-V1-java-source",
+ ":android.hardware.tv.hdmi.earc-V1-java-source",
":statslog-art-java-gen",
":statslog-contexthub-java-gen",
":services.core-sources",
@@ -160,6 +162,7 @@
"android.hardware.tv.cec-V1.1-java",
"android.hardware.tv.hdmi.cec-V1-java",
"android.hardware.tv.hdmi.connection-V1-java",
+ "android.hardware.tv.hdmi.earc-V1-java",
"android.hardware.weaver-V1.0-java",
"android.hardware.weaver-V2-java",
"android.hardware.biometrics.face-V1.0-java",
@@ -170,7 +173,7 @@
"android.hardware.ir-V1-java",
"android.hardware.rebootescrow-V1-java",
"android.hardware.soundtrigger-V2.3-java",
- "android.hardware.power.stats-V1-java",
+ "android.hardware.power.stats-V2-java",
"android.hardware.power-V4-java",
"android.hidl.manager-V1.2-java",
"icu4j_calendar_astronomer",
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index f101e73..f8e79e5 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -112,11 +112,11 @@
/** Observer called whenever the list of packages changes */
public interface PackageListObserver {
/** A package was added to the system. */
- void onPackageAdded(@NonNull String packageName, int uid);
+ default void onPackageAdded(@NonNull String packageName, int uid) {}
/** A package was changed - either installed for a specific user or updated. */
default void onPackageChanged(@NonNull String packageName, int uid) {}
/** A package was removed from the system. */
- void onPackageRemoved(@NonNull String packageName, int uid);
+ default void onPackageRemoved(@NonNull String packageName, int uid) {}
}
/**
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 71a4c73..b41664f 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -189,15 +189,20 @@
private long mLastBatteryLevelChangedSentMs;
private Bundle mBatteryChangedOptions = BroadcastOptions.makeRemovingMatchingFilter(
- new IntentFilter(Intent.ACTION_BATTERY_CHANGED)).toBundle();
+ new IntentFilter(Intent.ACTION_BATTERY_CHANGED)).setDeferUntilActive(true)
+ .toBundle();
private Bundle mPowerConnectedOptions = BroadcastOptions.makeRemovingMatchingFilter(
- new IntentFilter(Intent.ACTION_POWER_DISCONNECTED)).toBundle();
+ new IntentFilter(Intent.ACTION_POWER_DISCONNECTED)).setDeferUntilActive(true)
+ .toBundle();
private Bundle mPowerDisconnectedOptions = BroadcastOptions.makeRemovingMatchingFilter(
- new IntentFilter(Intent.ACTION_POWER_CONNECTED)).toBundle();
+ new IntentFilter(Intent.ACTION_POWER_CONNECTED)).setDeferUntilActive(true)
+ .toBundle();
private Bundle mBatteryLowOptions = BroadcastOptions.makeRemovingMatchingFilter(
- new IntentFilter(Intent.ACTION_BATTERY_OKAY)).toBundle();
+ new IntentFilter(Intent.ACTION_BATTERY_OKAY)).setDeferUntilActive(true)
+ .toBundle();
private Bundle mBatteryOkayOptions = BroadcastOptions.makeRemovingMatchingFilter(
- new IntentFilter(Intent.ACTION_BATTERY_LOW)).toBundle();
+ new IntentFilter(Intent.ACTION_BATTERY_LOW)).setDeferUntilActive(true)
+ .toBundle();
private MetricsLogger mMetricsLogger;
diff --git a/services/core/java/com/android/server/BinaryTransparencyService.java b/services/core/java/com/android/server/BinaryTransparencyService.java
index 819c948..661319f3 100644
--- a/services/core/java/com/android/server/BinaryTransparencyService.java
+++ b/services/core/java/com/android/server/BinaryTransparencyService.java
@@ -64,6 +64,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.IBinaryTransparencyService;
import com.android.internal.util.FrameworkStatsLog;
+import com.android.server.pm.ApexManager;
import libcore.util.HexEncoding;
@@ -531,27 +532,30 @@
pw.println("|--> Pre-installed package install location: "
+ origPackageFilepath);
- if (useSha256) {
- String sha256Digest = PackageUtils.computeSha256DigestForLargeFile(
- origPackageFilepath, PackageUtils.createLargeFileBuffer());
- pw.println("|--> Pre-installed package SHA-256 digest: "
- + sha256Digest);
- }
+ if (!origPackageFilepath.equals(APEX_PRELOAD_LOCATION_ERROR)) {
+ if (useSha256) {
+ String sha256Digest = PackageUtils.computeSha256DigestForLargeFile(
+ origPackageFilepath, PackageUtils.createLargeFileBuffer());
+ pw.println("|--> Pre-installed package SHA-256 digest: "
+ + sha256Digest);
+ }
-
- Map<Integer, byte[]> contentDigests = computeApkContentDigest(
- origPackageFilepath);
- if (contentDigests == null) {
- pw.println("ERROR: Failed to compute package content digest for "
- + origPackageFilepath);
- } else {
- for (Map.Entry<Integer, byte[]> entry : contentDigests.entrySet()) {
- Integer algorithmId = entry.getKey();
- byte[] contentDigest = entry.getValue();
- pw.println("|--> Pre-installed package content digest: "
- + HexEncoding.encodeToString(contentDigest, false));
- pw.println("|--> Pre-installed package content digest algorithm: "
- + translateContentDigestAlgorithmIdToString(algorithmId));
+ Map<Integer, byte[]> contentDigests = computeApkContentDigest(
+ origPackageFilepath);
+ if (contentDigests == null) {
+ pw.println("|--> ERROR: Failed to compute package content digest "
+ + "for " + origPackageFilepath);
+ } else {
+ for (Map.Entry<Integer, byte[]> entry : contentDigests.entrySet()) {
+ Integer algorithmId = entry.getKey();
+ byte[] contentDigest = entry.getValue();
+ pw.println("|--> Pre-installed package content digest: "
+ + HexEncoding.encodeToString(contentDigest, false));
+ pw.println("|--> Pre-installed package content digest "
+ + "algorithm: "
+ + translateContentDigestAlgorithmIdToString(
+ algorithmId));
+ }
}
}
}
@@ -1263,10 +1267,15 @@
private String getOriginalApexPreinstalledLocation(String packageName,
String currentInstalledLocation) {
try {
+ // It appears that only apexd knows the preinstalled location, and it uses module name
+ // as the identifier instead of package name. Given the input is a package name, we
+ // need to covert to module name.
+ final String moduleName = ApexManager.getInstance().getApexModuleNameForPackageName(
+ packageName);
IApexService apexService = IApexService.Stub.asInterface(
Binder.allowBlocking(ServiceManager.waitForService("apexservice")));
for (ApexInfo info : apexService.getAllPackages()) {
- if (packageName.equals(info.moduleName)) {
+ if (moduleName.equals(info.moduleName)) {
return info.preinstalledModulePath;
}
}
diff --git a/services/core/java/com/android/server/SystemConfig.java b/services/core/java/com/android/server/SystemConfig.java
index 2fc0712..ff75796 100644
--- a/services/core/java/com/android/server/SystemConfig.java
+++ b/services/core/java/com/android/server/SystemConfig.java
@@ -1476,6 +1476,8 @@
addFeature(PackageManager.FEATURE_IPSEC_TUNNELS, 0);
}
+ enableIpSecTunnelMigrationOnVsrUAndAbove();
+
if (isErofsSupported()) {
if (isKernelVersionAtLeast(5, 10)) {
addFeature(PackageManager.FEATURE_EROFS, 0);
@@ -1489,6 +1491,18 @@
}
}
+ // This method only enables a new Android feature added in U and will not have impact on app
+ // compatibility
+ @SuppressWarnings("AndroidFrameworkCompatChange")
+ private void enableIpSecTunnelMigrationOnVsrUAndAbove() {
+ final int vsrApi =
+ SystemProperties.getInt(
+ "ro.vendor.api_level", Build.VERSION.DEVICE_INITIAL_SDK_INT);
+ if (vsrApi > Build.VERSION_CODES.TIRAMISU) {
+ addFeature(PackageManager.FEATURE_IPSEC_TUNNEL_MIGRATION, 0);
+ }
+ }
+
private void addFeature(String name, int version) {
FeatureInfo fi = mAvailableFeatures.get(name);
if (fi == null) {
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 88492ed..35b5f1b 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -2010,7 +2010,7 @@
@Override
public void hasFeatures(IAccountManagerResponse response,
- Account account, String[] features, String opPackageName) {
+ Account account, String[] features, int userId, String opPackageName) {
int callingUid = Binder.getCallingUid();
mAppOpsManager.checkPackage(callingUid, opPackageName);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
@@ -2018,12 +2018,22 @@
+ ", response " + response
+ ", features " + Arrays.toString(features)
+ ", caller's uid " + callingUid
+ + ", userId " + userId
+ ", pid " + Binder.getCallingPid());
}
Preconditions.checkArgument(account != null, "account cannot be null");
Preconditions.checkArgument(response != null, "response cannot be null");
Preconditions.checkArgument(features != null, "features cannot be null");
- int userId = UserHandle.getCallingUserId();
+
+ if (userId != UserHandle.getCallingUserId()
+ && callingUid != Process.SYSTEM_UID
+ && mContext.checkCallingOrSelfPermission(
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("User " + UserHandle.getCallingUserId()
+ + " trying to check account features for " + userId);
+ }
+
checkReadAccountsPermitted(callingUid, account.type, userId,
opPackageName);
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index bcea40e5..9154231 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -112,6 +112,7 @@
import android.app.ActivityThread;
import android.app.AppGlobals;
import android.app.AppOpsManager;
+import android.app.ForegroundServiceDelegationOptions;
import android.app.ForegroundServiceStartNotAllowedException;
import android.app.ForegroundServiceTypePolicy;
import android.app.ForegroundServiceTypePolicy.ForegroundServicePolicyCheckCode;
@@ -3181,7 +3182,8 @@
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, final IServiceConnection connection, int flags,
String instanceName, boolean isSdkSandboxService, int sdkSandboxClientAppUid,
- String sdkSandboxClientAppPackage, String callingPackage, final int userId)
+ String sdkSandboxClientAppPackage, IApplicationThread sdkSandboxClientApplicationThread,
+ String callingPackage, final int userId)
throws TransactionTooLargeException {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "bindService: " + service
+ " type=" + resolvedType + " conn=" + connection.asBinder()
@@ -3271,6 +3273,10 @@
final boolean allowInstant = (flags & Context.BIND_ALLOW_INSTANT) != 0;
final boolean inSharedIsolatedProcess = (flags & Context.BIND_SHARED_ISOLATED_PROCESS) != 0;
+ ProcessRecord attributedApp = null;
+ if (sdkSandboxClientAppUid > 0) {
+ attributedApp = mAm.getRecordForAppLOSP(sdkSandboxClientApplicationThread);
+ }
ServiceLookupResult res = retrieveServiceLocked(service, instanceName,
isSdkSandboxService, sdkSandboxClientAppUid, sdkSandboxClientAppPackage,
resolvedType, callingPackage, callingPid, callingUid, userId, true, callerFg,
@@ -3283,7 +3289,7 @@
return -1;
}
ServiceRecord s = res.record;
- final AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
+ final AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp, attributedApp);
final ProcessServiceRecord clientPsr = b.client.mServices;
if (clientPsr.numberOfConnections() >= mAm.mConstants.mMaxServiceConnectionsPerProcess) {
Slog.w(TAG, "bindService exceeded max service connection number per process, "
diff --git a/services/core/java/com/android/server/am/ActivityManagerLocal.java b/services/core/java/com/android/server/am/ActivityManagerLocal.java
index 5175a31..abaa8c7 100644
--- a/services/core/java/com/android/server/am/ActivityManagerLocal.java
+++ b/services/core/java/com/android/server/am/ActivityManagerLocal.java
@@ -17,7 +17,6 @@
package com.android.server.am;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.content.Context;
@@ -76,6 +75,8 @@
* @param conn Receives information as the service is started and stopped.
* This must be a valid ServiceConnection object; it must not be null.
* @param clientAppUid Uid of the app for which the sdk sandbox process needs to be spawned.
+ * @param clientApplicationThread ApplicationThread object of the app for which the sdk sandboox
+ * is spawned.
* @param clientAppPackage Package of the app for which the sdk sandbox process needs to
* be spawned. This package must belong to the clientAppUid.
* @param processName Unique identifier for the service instance. Each unique name here will
@@ -91,6 +92,19 @@
*/
@SuppressLint("RethrowRemoteException")
boolean bindSdkSandboxService(@NonNull Intent service, @NonNull ServiceConnection conn,
+ int clientAppUid, @NonNull IBinder clientApplicationThread,
+ @NonNull String clientAppPackage, @NonNull String processName,
+ @Context.BindServiceFlags int flags)
+ throws RemoteException;
+
+ /**
+ * @deprecated Please use
+ * {@link #bindSdkSandboxService(Intent, ServiceConnection, int, IBinder, String, String, int)}
+ *
+ * This API can't be deleted yet because it can be used by early AdService module versions.
+ */
+ @SuppressLint("RethrowRemoteException")
+ boolean bindSdkSandboxService(@NonNull Intent service, @NonNull ServiceConnection conn,
int clientAppUid, @NonNull String clientAppPackage, @NonNull String processName,
@Context.BindServiceFlags int flags)
throws RemoteException;
@@ -103,28 +117,4 @@
* sandbox. This is obtained using {@link Context#getIApplicationThreadBinder()}.
*/
void killSdkSandboxClientAppProcess(@NonNull IBinder clientApplicationThreadBinder);
-
- /**
- * Start a foreground service delegate.
- * @param options foreground service delegate options.
- * @param connection a service connection served as callback to caller.
- * @return true if delegate is started successfully, false otherwise.
- * @hide
- */
- boolean startForegroundServiceDelegate(@NonNull ForegroundServiceDelegationOptions options,
- @Nullable ServiceConnection connection);
-
- /**
- * Stop a foreground service delegate.
- * @param options the foreground service delegate options.
- * @hide
- */
- void stopForegroundServiceDelegate(@NonNull ForegroundServiceDelegationOptions options);
-
- /**
- * Stop a foreground service delegate by service connection.
- * @param connection service connection used to start delegate previously.
- * @hide
- */
- void stopForegroundServiceDelegate(@NonNull ServiceConnection connection);
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index fc6d30b..09c4eb2 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -159,6 +159,8 @@
import android.Manifest.permission;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.PermissionMethod;
+import android.annotation.PermissionName;
import android.annotation.UserIdInt;
import android.app.Activity;
import android.app.ActivityClient;
@@ -184,6 +186,7 @@
import android.app.BroadcastOptions;
import android.app.ComponentOptions;
import android.app.ContentProviderHolder;
+import android.app.ForegroundServiceDelegationOptions;
import android.app.IActivityController;
import android.app.IActivityManager;
import android.app.IApplicationThread;
@@ -251,8 +254,6 @@
import android.content.pm.PackageManagerInternal;
import android.content.pm.ParceledListSlice;
import android.content.pm.PermissionInfo;
-import android.content.pm.PermissionMethod;
-import android.content.pm.PermissionName;
import android.content.pm.ProcessInfo;
import android.content.pm.ProviderInfo;
import android.content.pm.ProviderInfoList;
@@ -399,7 +400,6 @@
import com.android.server.LocalManagerRegistry;
import com.android.server.LocalServices;
import com.android.server.LockGuard;
-import com.android.server.NetworkManagementInternal;
import com.android.server.PackageWatchdog;
import com.android.server.ServiceThread;
import com.android.server.SystemConfig;
@@ -417,6 +417,7 @@
import com.android.server.firewall.IntentFirewall;
import com.android.server.graphics.fonts.FontManagerInternal;
import com.android.server.job.JobSchedulerInternal;
+import com.android.server.net.NetworkManagementInternal;
import com.android.server.os.NativeTombstoneManager;
import com.android.server.pm.Computer;
import com.android.server.pm.Installer;
@@ -1441,6 +1442,9 @@
private boolean mWaitForDebugger = false;
@GuardedBy("this")
+ private boolean mSuspendUponWait = false;
+
+ @GuardedBy("this")
private boolean mDebugTransient = false;
@GuardedBy("this")
@@ -5010,9 +5014,15 @@
try {
int testMode = ApplicationThreadConstants.DEBUG_OFF;
if (mDebugApp != null && mDebugApp.equals(processName)) {
- testMode = mWaitForDebugger
- ? ApplicationThreadConstants.DEBUG_WAIT
- : ApplicationThreadConstants.DEBUG_ON;
+ if (mWaitForDebugger) {
+ if (mSuspendUponWait) {
+ testMode = ApplicationThreadConstants.DEBUG_SUSPEND;
+ } else {
+ testMode = ApplicationThreadConstants.DEBUG_WAIT;
+ }
+ } else {
+ testMode = ApplicationThreadConstants.DEBUG_ON;
+ }
app.setDebugging(true);
if (mDebugTransient) {
mDebugApp = mOrigDebugApp;
@@ -7159,6 +7169,11 @@
public void setDebugApp(String packageName, boolean waitForDebugger,
boolean persistent) {
+ setDebugApp(packageName, waitForDebugger, persistent, false);
+ }
+
+ private void setDebugApp(String packageName, boolean waitForDebugger,
+ boolean persistent, boolean suspendUponWait) {
enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
"setDebugApp()");
@@ -7184,6 +7199,7 @@
}
mDebugApp = packageName;
mWaitForDebugger = waitForDebugger;
+ mSuspendUponWait = suspendUponWait;
mDebugTransient = !persistent;
if (packageName != null) {
forceStopPackageLocked(packageName, -1, false, false, true, true,
@@ -13107,13 +13123,15 @@
String resolvedType, IServiceConnection connection, int flags, String instanceName,
String callingPackage, int userId) throws TransactionTooLargeException {
return bindServiceInstance(caller, token, service, resolvedType, connection, flags,
- instanceName, false, INVALID_UID, null, callingPackage, userId);
+ instanceName, false, INVALID_UID, null, null, callingPackage, userId);
}
private int bindServiceInstance(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, IServiceConnection connection, int flags, String instanceName,
boolean isSdkSandboxService, int sdkSandboxClientAppUid,
- String sdkSandboxClientAppPackage, String callingPackage, int userId)
+ String sdkSandboxClientAppPackage,
+ IApplicationThread sdkSandboxClientApplicationThread,
+ String callingPackage, int userId)
throws TransactionTooLargeException {
enforceNotIsolatedCaller("bindService");
enforceAllowedToStartOrBindServiceIfSdkSandbox(service);
@@ -13152,7 +13170,8 @@
synchronized (this) {
return mServices.bindServiceLocked(caller, token, service, resolvedType, connection,
flags, instanceName, isSdkSandboxService, sdkSandboxClientAppUid,
- sdkSandboxClientAppPackage, callingPackage, userId);
+ sdkSandboxClientAppPackage, sdkSandboxClientApplicationThread,
+ callingPackage, userId);
}
} finally {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
@@ -13517,12 +13536,17 @@
public Intent registerReceiverWithFeature(IApplicationThread caller, String callerPackage,
String callerFeatureId, String receiverId, IIntentReceiver receiver,
IntentFilter filter, String permission, int userId, int flags) {
+ enforceNotIsolatedCaller("registerReceiver");
+
// Allow Sandbox process to register only unexported receivers.
- if ((flags & Context.RECEIVER_NOT_EXPORTED) != 0) {
- enforceNotIsolatedCaller("registerReceiver");
- } else if (mSdkSandboxSettings.isBroadcastReceiverRestrictionsEnforced()) {
- enforceNotIsolatedOrSdkSandboxCaller("registerReceiver");
+ boolean unexported = (flags & Context.RECEIVER_NOT_EXPORTED) != 0;
+ if (mSdkSandboxSettings.isBroadcastReceiverRestrictionsEnforced()
+ && Process.isSdkSandboxUid(Binder.getCallingUid())
+ && !unexported) {
+ throw new SecurityException("SDK sandbox process not allowed to call "
+ + "registerReceiver");
}
+
ArrayList<Intent> stickyIntents = null;
ProcessRecord callerApp = null;
final boolean visibleToInstantApps
@@ -14108,8 +14132,16 @@
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,
(sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
+ " ordered=" + ordered + " userid=" + userId);
- if ((resultTo != null) && !ordered && !mEnableModernQueue) {
- Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
+ if ((resultTo != null) && !ordered) {
+ if (!mEnableModernQueue) {
+ Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
+ }
+ if (!UserHandle.isCore(callingUid)) {
+ String msg = "Unauthorized unordered resultTo broadcast "
+ + intent + " sent from uid " + callingUid;
+ Slog.w(TAG, msg);
+ throw new SecurityException(msg);
+ }
}
userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true,
@@ -14190,6 +14222,18 @@
}
}
+ // resultTo broadcasts are always infinitely deferrable.
+ if ((resultTo != null) && !ordered && mEnableModernQueue) {
+ if (brOptions == null) {
+ brOptions = BroadcastOptions.makeBasic();
+ }
+ brOptions.setDeferUntilActive(true);
+ }
+
+ if (ordered && brOptions != null && brOptions.isDeferUntilActive()) {
+ throw new IllegalArgumentException("Ordered broadcasts can't be deferred until active");
+ }
+
// Verify that protected broadcasts are only being sent by system code,
// and that system code is only sending protected broadcasts.
final boolean isProtectedBroadcast;
@@ -16939,7 +16983,8 @@
@Override
public boolean bindSdkSandboxService(Intent service, ServiceConnection conn,
- int clientAppUid, String clientAppPackage, String processName, int flags)
+ int clientAppUid, IBinder clientApplicationThread, String clientAppPackage,
+ String processName, int flags)
throws RemoteException {
if (service == null) {
throw new IllegalArgumentException("intent is null");
@@ -16964,14 +17009,40 @@
}
Handler handler = mContext.getMainThreadHandler();
-
+ IApplicationThread clientApplicationThreadVerified = null;
+ if (clientApplicationThread != null) {
+ // Make sure this is a valid application process
+ synchronized (this) {
+ final ProcessRecord rec = getRecordForAppLOSP(clientApplicationThread);
+ if (rec == null) {
+ // This could happen if the calling process has disappeared; no need for the
+ // sandbox to be even started in this case.
+ Slog.i(TAG, "clientApplicationThread process not found.");
+ return false;
+ }
+ if (rec.info.uid != clientAppUid) {
+ throw new IllegalArgumentException("clientApplicationThread does not match "
+ + " client uid");
+ }
+ clientApplicationThreadVerified = rec.getThread();
+ }
+ }
final IServiceConnection sd = mContext.getServiceDispatcher(conn, handler, flags);
service.prepareToLeaveProcess(mContext);
return ActivityManagerService.this.bindServiceInstance(
mContext.getIApplicationThread(), mContext.getActivityToken(), service,
service.resolveTypeIfNeeded(mContext.getContentResolver()), sd, flags,
processName, /*isSdkSandboxService*/ true, clientAppUid, clientAppPackage,
- mContext.getOpPackageName(), UserHandle.getUserId(clientAppUid)) != 0;
+ clientApplicationThreadVerified, mContext.getOpPackageName(),
+ UserHandle.getUserId(clientAppUid)) != 0;
+ }
+
+ @Override
+ public boolean bindSdkSandboxService(Intent service, ServiceConnection conn,
+ int clientAppUid, String clientAppPackage, String processName, int flags)
+ throws RemoteException {
+ return bindSdkSandboxService(service, conn, clientAppUid,
+ null /* clientApplicationThread */, clientAppPackage, processName, flags);
}
@Override
@@ -17816,6 +17887,10 @@
setDebugApp(aInfo.processName, true, false);
}
+ if ((startFlags & ActivityManager.START_FLAG_DEBUG_SUSPEND) != 0) {
+ setDebugApp(aInfo.processName, true, false, true);
+ }
+
if ((startFlags & ActivityManager.START_FLAG_NATIVE_DEBUGGING) != 0) {
setNativeDebuggingAppLocked(aInfo.applicationInfo, aInfo.processName);
}
@@ -18549,10 +18624,10 @@
for (int i = delegates.size() - 1; i >= 0; i--) {
final ForegroundServiceDelegationOptions options = delegates.get(i);
if (isStart) {
- ((ActivityManagerLocal) mInternal).startForegroundServiceDelegate(options,
+ mInternal.startForegroundServiceDelegate(options,
null /* connection */);
} else {
- ((ActivityManagerLocal) mInternal).stopForegroundServiceDelegate(options);
+ mInternal.stopForegroundServiceDelegate(options);
}
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 80684bf..0a73eaa 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -46,6 +46,7 @@
import android.app.ActivityTaskManager.RootTaskInfo;
import android.app.AppGlobals;
import android.app.BroadcastOptions;
+import android.app.ForegroundServiceDelegationOptions;
import android.app.IActivityController;
import android.app.IActivityManager;
import android.app.IActivityTaskManager;
@@ -411,6 +412,8 @@
public boolean handleOption(String opt, ShellCommand cmd) {
if (opt.equals("-D")) {
mStartFlags |= ActivityManager.START_FLAG_DEBUG;
+ } else if (opt.equals("--suspend")) {
+ mStartFlags |= ActivityManager.START_FLAG_DEBUG_SUSPEND;
} else if (opt.equals("-N")) {
mStartFlags |= ActivityManager.START_FLAG_NATIVE_DEBUGGING;
} else if (opt.equals("-W")) {
@@ -2153,19 +2156,24 @@
boolean success;
String displaySuffix;
- if (displayId == Display.INVALID_DISPLAY) {
- success = mInterface.startUserInBackgroundWithListener(userId, waiter);
- displaySuffix = "";
- } else {
- if (!UserManager.isVisibleBackgroundUsersEnabled()) {
- pw.println("Not supported");
- return -1;
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "shell_runStartUser" + userId);
+ try {
+ if (displayId == Display.INVALID_DISPLAY) {
+ success = mInterface.startUserInBackgroundWithListener(userId, waiter);
+ displaySuffix = "";
+ } else {
+ if (!UserManager.isVisibleBackgroundUsersEnabled()) {
+ pw.println("Not supported");
+ return -1;
+ }
+ success = mInterface.startUserInBackgroundVisibleOnDisplay(userId, displayId);
+ displaySuffix = " on display " + displayId;
}
- success = mInterface.startUserInBackgroundVisibleOnDisplay(userId, displayId);
- displaySuffix = " on display " + displayId;
- }
- if (wait && success) {
- success = waiter.waitForFinish(USER_OPERATION_TIMEOUT_MS);
+ if (wait && success) {
+ success = waiter.waitForFinish(USER_OPERATION_TIMEOUT_MS);
+ }
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
if (success) {
diff --git a/services/core/java/com/android/server/am/AppBindRecord.java b/services/core/java/com/android/server/am/AppBindRecord.java
index 28756a4..f7b3d3a 100644
--- a/services/core/java/com/android/server/am/AppBindRecord.java
+++ b/services/core/java/com/android/server/am/AppBindRecord.java
@@ -28,13 +28,15 @@
final ServiceRecord service; // The running service.
final IntentBindRecord intent; // The intent we are bound to.
final ProcessRecord client; // Who has started/bound the service.
-
+ final ProcessRecord attributedClient; // The binding was done by the system on behalf
+ // of 'attributedClient'
final ArraySet<ConnectionRecord> connections = new ArraySet<>();
// All ConnectionRecord for this client.
void dump(PrintWriter pw, String prefix) {
pw.println(prefix + "service=" + service);
pw.println(prefix + "client=" + client);
+ pw.println(prefix + "attributedClient=" + attributedClient);
dumpInIntentBind(pw, prefix);
}
@@ -50,10 +52,11 @@
}
AppBindRecord(ServiceRecord _service, IntentBindRecord _intent,
- ProcessRecord _client) {
+ ProcessRecord _client, ProcessRecord _attributedClient) {
service = _service;
intent = _intent;
client = _client;
+ attributedClient = _attributedClient;
}
public String toString() {
diff --git a/services/core/java/com/android/server/am/BroadcastProcessQueue.java b/services/core/java/com/android/server/am/BroadcastProcessQueue.java
index fa7748b..d7cca60 100644
--- a/services/core/java/com/android/server/am/BroadcastProcessQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastProcessQueue.java
@@ -62,6 +62,7 @@
*/
// @NotThreadSafe
class BroadcastProcessQueue {
+ static final boolean VERBOSE = false;
final @NonNull BroadcastConstants constants;
final @NonNull String processName;
final int uid;
@@ -168,10 +169,14 @@
/**
* Count of pending broadcasts of these various flavors.
*/
+ private int mCountEnqueued;
+ private int mCountDeferred;
private int mCountForeground;
+ private int mCountForegroundDeferred;
private int mCountOrdered;
private int mCountAlarm;
private int mCountPrioritized;
+ private int mCountPrioritizedDeferred;
private int mCountInteractive;
private int mCountResultTo;
private int mCountInstrumented;
@@ -226,10 +231,10 @@
* used for ordered broadcasts and priority traunches.
*/
public void enqueueOrReplaceBroadcast(@NonNull BroadcastRecord record, int recordIndex,
- @NonNull BroadcastConsumer replacedBroadcastConsumer) {
+ @NonNull BroadcastConsumer replacedBroadcastConsumer, boolean wouldBeSkipped) {
if (record.isReplacePending()) {
final boolean didReplace = replaceBroadcast(record, recordIndex,
- replacedBroadcastConsumer);
+ replacedBroadcastConsumer, wouldBeSkipped);
if (didReplace) {
return;
}
@@ -240,13 +245,14 @@
SomeArgs newBroadcastArgs = SomeArgs.obtain();
newBroadcastArgs.arg1 = record;
newBroadcastArgs.argi1 = recordIndex;
+ newBroadcastArgs.argi2 = (wouldBeSkipped ? 1 : 0);
// Cross-broadcast prioritization policy: some broadcasts might warrant being
// issued ahead of others that are already pending, for example if this new
// broadcast is in a different delivery class or is tied to a direct user interaction
// with implicit responsiveness expectations.
getQueueForBroadcast(record).addLast(newBroadcastArgs);
- onBroadcastEnqueued(record, recordIndex);
+ onBroadcastEnqueued(record, recordIndex, wouldBeSkipped);
}
/**
@@ -258,11 +264,12 @@
* {@code false} otherwise.
*/
private boolean replaceBroadcast(@NonNull BroadcastRecord record, int recordIndex,
- @NonNull BroadcastConsumer replacedBroadcastConsumer) {
+ @NonNull BroadcastConsumer replacedBroadcastConsumer, boolean wouldBeSkipped) {
final int count = mPendingQueues.size();
for (int i = 0; i < count; ++i) {
final ArrayDeque<SomeArgs> queue = mPendingQueues.get(i);
- if (replaceBroadcastInQueue(queue, record, recordIndex, replacedBroadcastConsumer)) {
+ if (replaceBroadcastInQueue(queue, record, recordIndex,
+ replacedBroadcastConsumer, wouldBeSkipped)) {
return true;
}
}
@@ -279,13 +286,15 @@
*/
private boolean replaceBroadcastInQueue(@NonNull ArrayDeque<SomeArgs> queue,
@NonNull BroadcastRecord record, int recordIndex,
- @NonNull BroadcastConsumer replacedBroadcastConsumer) {
+ @NonNull BroadcastConsumer replacedBroadcastConsumer,
+ boolean wouldBeSkipped) {
final Iterator<SomeArgs> it = queue.descendingIterator();
final Object receiver = record.receivers.get(recordIndex);
while (it.hasNext()) {
final SomeArgs args = it.next();
final BroadcastRecord testRecord = (BroadcastRecord) args.arg1;
final int testRecordIndex = args.argi1;
+ final boolean testWouldBeSkipped = (args.argi2 == 1);
final Object testReceiver = testRecord.receivers.get(testRecordIndex);
if ((record.callingUid == testRecord.callingUid)
&& (record.userId == testRecord.userId)
@@ -295,9 +304,10 @@
// Exact match found; perform in-place swap
args.arg1 = record;
args.argi1 = recordIndex;
+ args.argi2 = (wouldBeSkipped ? 1 : 0);
record.copyEnqueueTimeFrom(testRecord);
- onBroadcastDequeued(testRecord, testRecordIndex);
- onBroadcastEnqueued(record, recordIndex);
+ onBroadcastDequeued(testRecord, testRecordIndex, testWouldBeSkipped);
+ onBroadcastEnqueued(record, recordIndex, wouldBeSkipped);
replacedBroadcastConsumer.accept(testRecord, testRecordIndex);
return true;
}
@@ -352,12 +362,13 @@
final SomeArgs args = it.next();
final BroadcastRecord record = (BroadcastRecord) args.arg1;
final int recordIndex = args.argi1;
+ final boolean recordWouldBeSkipped = (args.argi2 == 1);
if (predicate.test(record, recordIndex)) {
consumer.accept(record, recordIndex);
if (andRemove) {
args.recycle();
it.remove();
- onBroadcastDequeued(record, recordIndex);
+ onBroadcastDequeued(record, recordIndex, recordWouldBeSkipped);
}
didSomething = true;
}
@@ -423,7 +434,7 @@
}
public int getPreferredSchedulingGroupLocked() {
- if (mCountForeground > 0) {
+ if (mCountForeground > mCountForegroundDeferred) {
// We have a foreground broadcast somewhere down the queue, so
// boost priority until we drain them all
return ProcessList.SCHED_GROUP_DEFAULT;
@@ -469,10 +480,11 @@
final SomeArgs next = removeNextBroadcast();
mActive = (BroadcastRecord) next.arg1;
mActiveIndex = next.argi1;
+ final boolean wouldBeSkipped = (next.argi2 == 1);
mActiveCountSinceIdle++;
mActiveViaColdStart = false;
next.recycle();
- onBroadcastDequeued(mActive, mActiveIndex);
+ onBroadcastDequeued(mActive, mActiveIndex, wouldBeSkipped);
}
/**
@@ -489,8 +501,16 @@
/**
* Update summary statistics when the given record has been enqueued.
*/
- private void onBroadcastEnqueued(@NonNull BroadcastRecord record, int recordIndex) {
+ private void onBroadcastEnqueued(@NonNull BroadcastRecord record, int recordIndex,
+ boolean wouldBeSkipped) {
+ mCountEnqueued++;
+ if (record.deferUntilActive) {
+ mCountDeferred++;
+ }
if (record.isForeground()) {
+ if (record.deferUntilActive) {
+ mCountForegroundDeferred++;
+ }
mCountForeground++;
}
if (record.ordered) {
@@ -500,6 +520,9 @@
mCountAlarm++;
}
if (record.prioritized) {
+ if (record.deferUntilActive) {
+ mCountPrioritizedDeferred++;
+ }
mCountPrioritized++;
}
if (record.interactive) {
@@ -511,7 +534,8 @@
if (record.callerInstrumented) {
mCountInstrumented++;
}
- if (record.receivers.get(recordIndex) instanceof ResolveInfo) {
+ if (!wouldBeSkipped
+ && (record.receivers.get(recordIndex) instanceof ResolveInfo)) {
mCountManifest++;
}
invalidateRunnableAt();
@@ -520,8 +544,16 @@
/**
* Update summary statistics when the given record has been dequeued.
*/
- private void onBroadcastDequeued(@NonNull BroadcastRecord record, int recordIndex) {
+ private void onBroadcastDequeued(@NonNull BroadcastRecord record, int recordIndex,
+ boolean wouldBeSkipped) {
+ mCountEnqueued--;
+ if (record.deferUntilActive) {
+ mCountDeferred--;
+ }
if (record.isForeground()) {
+ if (record.deferUntilActive) {
+ mCountForegroundDeferred--;
+ }
mCountForeground--;
}
if (record.ordered) {
@@ -531,6 +563,9 @@
mCountAlarm--;
}
if (record.prioritized) {
+ if (record.deferUntilActive) {
+ mCountPrioritizedDeferred--;
+ }
mCountPrioritized--;
}
if (record.interactive) {
@@ -542,7 +577,8 @@
if (record.callerInstrumented) {
mCountInstrumented--;
}
- if (record.receivers.get(recordIndex) instanceof ResolveInfo) {
+ if (!wouldBeSkipped
+ && (record.receivers.get(recordIndex) instanceof ResolveInfo)) {
mCountManifest--;
}
invalidateRunnableAt();
@@ -711,7 +747,7 @@
* be delivered at some point in the future.
*/
public boolean isIdle() {
- return !isActive() && isEmpty();
+ return (!isActive() && isEmpty()) || isDeferredUntilActive();
}
/**
@@ -733,7 +769,8 @@
final boolean nextOffloadBeyond = (nextOffload == null)
|| ((BroadcastRecord) nextOffload.arg1).enqueueTime > barrierTime;
- return activeBeyond && nextBeyond && nextUrgentBeyond && nextOffloadBeyond;
+ return (activeBeyond && nextBeyond && nextUrgentBeyond && nextOffloadBeyond)
+ || isDeferredUntilActive();
}
public boolean isRunnable() {
@@ -741,6 +778,15 @@
return mRunnableAt != Long.MAX_VALUE;
}
+ public boolean isDeferredUntilActive() {
+ if (mRunnableAtInvalidated) updateRunnableAt();
+ return mRunnableAtReason == BroadcastProcessQueue.REASON_CACHED_INFINITE_DEFER;
+ }
+
+ public boolean hasDeferredBroadcasts() {
+ return (mCountDeferred > 0);
+ }
+
/**
* Return time at which this process is considered runnable. This is
* typically the time at which the next pending broadcast was first
@@ -776,6 +822,7 @@
static final int REASON_INSTRUMENTED = 5;
static final int REASON_PERSISTENT = 6;
static final int REASON_FORCE_DELAYED = 7;
+ static final int REASON_CACHED_INFINITE_DEFER = 8;
static final int REASON_CONTAINS_FOREGROUND = 10;
static final int REASON_CONTAINS_ORDERED = 11;
static final int REASON_CONTAINS_ALARM = 12;
@@ -794,6 +841,7 @@
REASON_INSTRUMENTED,
REASON_PERSISTENT,
REASON_FORCE_DELAYED,
+ REASON_CACHED_INFINITE_DEFER,
REASON_CONTAINS_FOREGROUND,
REASON_CONTAINS_ORDERED,
REASON_CONTAINS_ALARM,
@@ -816,6 +864,7 @@
case REASON_INSTRUMENTED: return "INSTRUMENTED";
case REASON_PERSISTENT: return "PERSISTENT";
case REASON_FORCE_DELAYED: return "FORCE_DELAYED";
+ case REASON_CACHED_INFINITE_DEFER: return "INFINITE_DEFER";
case REASON_CONTAINS_FOREGROUND: return "CONTAINS_FOREGROUND";
case REASON_CONTAINS_ORDERED: return "CONTAINS_ORDERED";
case REASON_CONTAINS_ALARM: return "CONTAINS_ALARM";
@@ -831,9 +880,16 @@
private boolean blockedOnOrderedDispatch(BroadcastRecord r, int index) {
final int blockedUntilTerminalCount = r.blockedUntilTerminalCount[index];
+ int existingDeferredCount = 0;
+ if (r.deferUntilActive) {
+ for (int i = 0; i < index; i++) {
+ if (r.deferredUntilActive[i]) existingDeferredCount++;
+ }
+ }
+
// We might be blocked waiting for other receivers to finish,
// typically for an ordered broadcast or priority traunches
- if (r.terminalCount < blockedUntilTerminalCount
+ if ((r.terminalCount + existingDeferredCount) < blockedUntilTerminalCount
&& !isDeliveryStateTerminal(r.getDeliveryState(index))) {
return true;
}
@@ -862,7 +918,7 @@
if (mForcedDelayedDurationMs > 0) {
mRunnableAt = runnableAt + mForcedDelayedDurationMs;
mRunnableAtReason = REASON_FORCE_DELAYED;
- } else if (mCountForeground > 0) {
+ } else if (mCountForeground > mCountForegroundDeferred) {
mRunnableAt = runnableAt + constants.DELAY_URGENT_MILLIS;
mRunnableAtReason = REASON_CONTAINS_FOREGROUND;
} else if (mCountInteractive > 0) {
@@ -880,12 +936,9 @@
} else if (mCountAlarm > 0) {
mRunnableAt = runnableAt;
mRunnableAtReason = REASON_CONTAINS_ALARM;
- } else if (mCountPrioritized > 0) {
+ } else if (mCountPrioritized > mCountPrioritizedDeferred) {
mRunnableAt = runnableAt;
mRunnableAtReason = REASON_CONTAINS_PRIORITIZED;
- } else if (mCountResultTo > 0) {
- mRunnableAt = runnableAt;
- mRunnableAtReason = REASON_CONTAINS_RESULT_TO;
} else if (mCountManifest > 0) {
mRunnableAt = runnableAt;
mRunnableAtReason = REASON_CONTAINS_MANIFEST;
@@ -893,8 +946,39 @@
mRunnableAt = runnableAt;
mRunnableAtReason = REASON_PERSISTENT;
} else if (mProcessCached) {
- mRunnableAt = runnableAt + constants.DELAY_CACHED_MILLIS;
- mRunnableAtReason = REASON_CACHED;
+ if (r.deferUntilActive) {
+ // All enqueued broadcasts are deferrable, defer
+ if (mCountDeferred == mCountEnqueued) {
+ mRunnableAt = Long.MAX_VALUE;
+ mRunnableAtReason = REASON_CACHED_INFINITE_DEFER;
+ } else {
+ // At least one enqueued broadcast isn't deferrable, repick time and reason
+ // for this record. If a later record is not deferrable and is one of these
+ // special cases, one of the cases above would have already caught that.
+ if (r.isForeground()) {
+ mRunnableAt = runnableAt + constants.DELAY_URGENT_MILLIS;
+ mRunnableAtReason = REASON_CONTAINS_FOREGROUND;
+ } else if (r.prioritized) {
+ mRunnableAt = runnableAt;
+ mRunnableAtReason = REASON_CONTAINS_PRIORITIZED;
+ } else if (r.resultTo != null) {
+ mRunnableAt = runnableAt;
+ mRunnableAtReason = REASON_CONTAINS_RESULT_TO;
+ } else {
+ mRunnableAt = runnableAt + constants.DELAY_CACHED_MILLIS;
+ mRunnableAtReason = REASON_CACHED;
+ }
+ }
+ } else {
+ // This record isn't deferrable
+ mRunnableAt = runnableAt + constants.DELAY_CACHED_MILLIS;
+ mRunnableAtReason = REASON_CACHED;
+ }
+ } else if (mCountResultTo > 0) {
+ // All resultTo broadcasts are infinitely deferrable, so if the app
+ // is already cached, they'll be deferred on the line above
+ mRunnableAt = runnableAt;
+ mRunnableAtReason = REASON_CONTAINS_RESULT_TO;
} else {
mRunnableAt = runnableAt + constants.DELAY_NORMAL_MILLIS;
mRunnableAtReason = REASON_NORMAL;
@@ -907,6 +991,15 @@
mRunnableAt = Math.min(mRunnableAt, runnableAt);
mRunnableAtReason = REASON_MAX_PENDING;
}
+
+ if (VERBOSE) {
+ Trace.instantForTrack(Trace.TRACE_TAG_ACTIVITY_MANAGER, "BroadcastQueue",
+ ((app != null) ? app.processName : "(null)")
+ + ":" + r.intent.toString() + ":"
+ + r.deferUntilActive
+ + ":" + mRunnableAt + " " + reasonToString(mRunnableAtReason)
+ + ":" + ((app != null) ? app.isCached() : "false"));
+ }
} else {
mRunnableAt = Long.MAX_VALUE;
mRunnableAtReason = REASON_EMPTY;
diff --git a/services/core/java/com/android/server/am/BroadcastQueueImpl.java b/services/core/java/com/android/server/am/BroadcastQueueImpl.java
index 8946ada1..a86efa3 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueImpl.java
@@ -397,11 +397,12 @@
+ ": " + r);
mService.notifyPackageUse(r.intent.getComponent().getPackageName(),
PackageManager.NOTIFY_PACKAGE_USE_BROADCAST_RECEIVER);
+ final boolean assumeDelivered = false;
thread.scheduleReceiverList(mReceiverBatch.manifestReceiver(
prepareReceiverIntent(r.intent, r.curFilteredExtras),
r.curReceiver, null /* compatInfo (unused but need to keep method signature) */,
- r.resultCode, r.resultData, r.resultExtras, r.ordered, r.userId,
- app.mState.getReportedProcState()));
+ r.resultCode, r.resultData, r.resultExtras, r.ordered, assumeDelivered,
+ r.userId, app.mState.getReportedProcState()));
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Process cur broadcast " + r + " DELIVERED for app " + app);
started = true;
@@ -735,9 +736,10 @@
// If we have an app thread, do the call through that so it is
// correctly ordered with other one-way calls.
try {
+ final boolean assumeDelivered = !ordered;
thread.scheduleReceiverList(mReceiverBatch.registeredReceiver(
receiver, intent, resultCode,
- data, extras, ordered, sticky, sendingUser,
+ data, extras, ordered, sticky, assumeDelivered, sendingUser,
app.mState.getReportedProcState()));
} catch (RemoteException ex) {
// Failed to call into the process. It's either dying or wedged. Kill it gently.
diff --git a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
index a994b1d..8fc4a21 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
@@ -385,6 +385,8 @@
// If app isn't running, and there's nothing in the queue, clean up
if (queue.isEmpty() && !queue.isActive() && !queue.isProcessWarm()) {
removeProcessQueue(queue.processName, queue.uid);
+ } else {
+ updateQueueDeferred(queue);
}
}
@@ -506,16 +508,7 @@
mService.updateOomAdjPendingTargetsLocked(OOM_ADJ_REASON_START_RECEIVER);
}
- if (waitingFor) {
- mWaitingFor.removeIf((pair) -> {
- if (pair.first.getAsBoolean()) {
- pair.second.countDown();
- return true;
- } else {
- return false;
- }
- });
- }
+ checkAndRemoveWaitingFor();
traceEnd(cookie);
}
@@ -637,11 +630,34 @@
final ArraySet<BroadcastRecord> replacedBroadcasts = new ArraySet<>();
final BroadcastConsumer replacedBroadcastConsumer =
(record, i) -> replacedBroadcasts.add(record);
+ boolean enqueuedBroadcast = false;
+
for (int i = 0; i < r.receivers.size(); i++) {
final Object receiver = r.receivers.get(i);
final BroadcastProcessQueue queue = getOrCreateProcessQueue(
getReceiverProcessName(receiver), getReceiverUid(receiver));
- queue.enqueueOrReplaceBroadcast(r, i, replacedBroadcastConsumer);
+
+ boolean wouldBeSkipped = false;
+ if (receiver instanceof ResolveInfo) {
+ // If the app is running but would not have been started if the process weren't
+ // running, we're going to deliver the broadcast but mark that it's not a manifest
+ // broadcast that would have started the app. This allows BroadcastProcessQueue to
+ // defer the broadcast as though it were a normal runtime receiver.
+ wouldBeSkipped = (mSkipPolicy.shouldSkipMessage(r, receiver) != null);
+ if (wouldBeSkipped && queue.app == null && !queue.getActiveViaColdStart()) {
+ // Skip receiver if there's no running app, the app is not being started, and
+ // the app wouldn't be launched for this broadcast
+ setDeliveryState(null, null, r, i, receiver, BroadcastRecord.DELIVERY_SKIPPED,
+ "skipped by policy to avoid cold start");
+ continue;
+ }
+ }
+ enqueuedBroadcast = true;
+ queue.enqueueOrReplaceBroadcast(r, i, replacedBroadcastConsumer, wouldBeSkipped);
+ if (r.isDeferUntilActive() && queue.isDeferredUntilActive()) {
+ setDeliveryState(queue, null, r, i, receiver, BroadcastRecord.DELIVERY_DEFERRED,
+ "deferred at enqueue time");
+ }
updateRunnableList(queue);
enqueueUpdateRunningList();
}
@@ -651,7 +667,7 @@
skipAndCancelReplacedBroadcasts(replacedBroadcasts);
// If nothing to dispatch, send any pending result immediately
- if (r.receivers.isEmpty()) {
+ if (r.receivers.isEmpty() || !enqueuedBroadcast) {
scheduleResultTo(r);
notifyFinishBroadcast(r);
}
@@ -872,21 +888,26 @@
return true;
}
+ final boolean assumeDelivered = isAssumedDelivered(r, index);
if (receiver instanceof BroadcastFilter) {
batch.schedule(((BroadcastFilter) receiver).receiverList.receiver,
receiverIntent, r.resultCode, r.resultData, r.resultExtras,
- r.ordered, r.initialSticky, r.userId,
+ r.ordered, r.initialSticky, assumeDelivered, r.userId,
app.mState.getReportedProcState(), r, index);
// TODO: consider making registered receivers of unordered
// broadcasts report results to detect ANRs
- if (!r.ordered) {
+ if (assumeDelivered) {
batch.success(r, index, BroadcastRecord.DELIVERY_DELIVERED, "assuming delivered");
return true;
}
} else {
batch.schedule(receiverIntent, ((ResolveInfo) receiver).activityInfo,
- null, r.resultCode, r.resultData, r.resultExtras, r.ordered, r.userId,
- app.mState.getReportedProcState(), r, index);
+ null, r.resultCode, r.resultData, r.resultExtras, r.ordered, assumeDelivered,
+ r.userId, app.mState.getReportedProcState(), r, index);
+ if (assumeDelivered) {
+ batch.success(r, index, BroadcastRecord.DELIVERY_DELIVERED, "assuming delivered");
+ return true;
+ }
}
return false;
@@ -975,7 +996,8 @@
* Return true if this receiver should be assumed to have been delivered.
*/
private boolean isAssumedDelivered(BroadcastRecord r, int index) {
- return (r.receivers.get(index) instanceof BroadcastFilter) && !r.ordered;
+ return (r.receivers.get(index) instanceof BroadcastFilter) && !r.ordered
+ && (r.resultTo == null);
}
/**
@@ -1034,10 +1056,11 @@
mService.mOomAdjuster.mCachedAppOptimizer.unfreezeTemporarily(
app, OOM_ADJ_REASON_FINISH_RECEIVER);
try {
+ final boolean assumeDelivered = true;
thread.scheduleReceiverList(mReceiverBatch.registeredReceiver(
r.resultTo, r.intent,
r.resultCode, r.resultData, r.resultExtras, false, r.initialSticky,
- r.userId, app.mState.getReportedProcState()));
+ assumeDelivered, r.userId, app.mState.getReportedProcState()));
} catch (RemoteException e) {
final String msg = "Failed to schedule result of " + r + " via " + app + ": " + e;
logw(msg);
@@ -1156,6 +1179,9 @@
mLocalHandler.removeMessages(MSG_DELIVERY_TIMEOUT_HARD, queue);
}
+ // Given that a receiver just finished, check if the "waitingFor" conditions are met.
+ checkAndRemoveWaitingFor();
+
if (early) {
// This is an early receiver that was transmitted as part of a group. The delivery
// state has been updated but don't make any further decisions.
@@ -1195,11 +1221,19 @@
@NonNull Object receiver, @DeliveryState int newDeliveryState, String reason) {
final int cookie = traceBegin("setDeliveryState");
final int oldDeliveryState = getDeliveryState(r, index);
+ boolean checkFinished = false;
// Only apply state when we haven't already reached a terminal state;
// this is how we ignore racing timeout messages
if (!isDeliveryStateTerminal(oldDeliveryState)) {
r.setDeliveryState(index, newDeliveryState);
+ if (oldDeliveryState == BroadcastRecord.DELIVERY_DEFERRED) {
+ r.deferredCount--;
+ } else if (newDeliveryState == BroadcastRecord.DELIVERY_DEFERRED) {
+ // If we're deferring a broadcast, maybe that's enough to unblock the final callback
+ r.deferredCount++;
+ checkFinished = true;
+ }
}
// Emit any relevant tracing results when we're changing the delivery
@@ -1217,7 +1251,8 @@
// bookkeeping to update for ordered broadcasts
if (!isDeliveryStateTerminal(oldDeliveryState)
&& isDeliveryStateTerminal(newDeliveryState)) {
- if (newDeliveryState != BroadcastRecord.DELIVERY_DELIVERED) {
+ if (DEBUG_BROADCAST
+ && newDeliveryState != BroadcastRecord.DELIVERY_DELIVERED) {
logw("Delivery state of " + r + " to " + receiver
+ " via " + app + " changed from "
+ deliveryStateToString(oldDeliveryState) + " to "
@@ -1226,9 +1261,12 @@
r.terminalCount++;
notifyFinishReceiver(queue, r, index, receiver);
-
- // When entire ordered broadcast finished, deliver final result
- final boolean recordFinished = (r.terminalCount == r.receivers.size());
+ checkFinished = true;
+ }
+ // When entire ordered broadcast finished, deliver final result
+ if (checkFinished) {
+ final boolean recordFinished =
+ ((r.terminalCount + r.deferredCount) == r.receivers.size());
if (recordFinished) {
scheduleResultTo(r);
}
@@ -1329,6 +1367,16 @@
r.resultExtras = null;
};
+ private final BroadcastConsumer mBroadcastConsumerDefer = (r, i) -> {
+ setDeliveryState(null, null, r, i, r.receivers.get(i), BroadcastRecord.DELIVERY_DEFERRED,
+ "mBroadcastConsumerDefer");
+ };
+
+ private final BroadcastConsumer mBroadcastConsumerUndoDefer = (r, i) -> {
+ setDeliveryState(null, null, r, i, r.receivers.get(i), BroadcastRecord.DELIVERY_PENDING,
+ "mBroadcastConsumerUndoDefer");
+ };
+
/**
* Verify that all known {@link #mProcessQueues} are in the state tested by
* the given {@link Predicate}.
@@ -1392,6 +1440,21 @@
}
}
+ private void updateQueueDeferred(
+ @NonNull BroadcastProcessQueue leaf) {
+ if (leaf.isDeferredUntilActive()) {
+ leaf.forEachMatchingBroadcast((r, i) -> {
+ return r.deferUntilActive && (r.getDeliveryState(i)
+ == BroadcastRecord.DELIVERY_PENDING);
+ }, mBroadcastConsumerDefer, false);
+ } else if (leaf.hasDeferredBroadcasts()) {
+ leaf.forEachMatchingBroadcast((r, i) -> {
+ return r.deferUntilActive && (r.getDeliveryState(i)
+ == BroadcastRecord.DELIVERY_DEFERRED);
+ }, mBroadcastConsumerUndoDefer, false);
+ }
+ }
+
@Override
public void start(@NonNull ContentResolver resolver) {
mFgConstants.startObserving(mHandler, resolver);
@@ -1404,6 +1467,7 @@
BroadcastProcessQueue leaf = mProcessQueues.get(uid);
while (leaf != null) {
leaf.setProcessCached(cached);
+ updateQueueDeferred(leaf);
updateRunnableList(leaf);
leaf = leaf.processNameNext;
}
@@ -1446,7 +1510,7 @@
waitFor(() -> isBeyondBarrierLocked(now, pw));
}
- public void waitFor(@NonNull BooleanSupplier condition) {
+ private void waitFor(@NonNull BooleanSupplier condition) {
final CountDownLatch latch = new CountDownLatch(1);
synchronized (mService) {
mWaitingFor.add(Pair.create(condition, latch));
@@ -1468,6 +1532,19 @@
}
}
+ private void checkAndRemoveWaitingFor() {
+ if (!mWaitingFor.isEmpty()) {
+ mWaitingFor.removeIf((pair) -> {
+ if (pair.first.getAsBoolean()) {
+ pair.second.countDown();
+ return true;
+ } else {
+ return false;
+ }
+ });
+ }
+ }
+
@Override
public void forceDelayBroadcastDelivery(@NonNull String targetPackage,
long delayedDurationMs) {
diff --git a/services/core/java/com/android/server/am/BroadcastReceiverBatch.java b/services/core/java/com/android/server/am/BroadcastReceiverBatch.java
index a826458..226647c 100644
--- a/services/core/java/com/android/server/am/BroadcastReceiverBatch.java
+++ b/services/core/java/com/android/server/am/BroadcastReceiverBatch.java
@@ -19,8 +19,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ReceiverInfo;
-import android.content.Intent;
import android.content.IIntentReceiver;
+import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.CompatibilityInfo;
import android.os.Bundle;
@@ -171,12 +171,13 @@
// Add a ReceiverInfo for a registered receiver.
void schedule(@Nullable IIntentReceiver receiver, Intent intent,
int resultCode, @Nullable String data, @Nullable Bundle extras, boolean ordered,
- boolean sticky, int sendingUser, int processState,
+ boolean sticky, boolean assumeDelivered, int sendingUser, int processState,
@Nullable BroadcastRecord r, int index) {
ReceiverInfo ri = new ReceiverInfo();
ri.intent = intent;
ri.data = data;
ri.extras = extras;
+ ri.assumeDelivered = assumeDelivered;
ri.sendingUser = sendingUser;
ri.processState = processState;
ri.resultCode = resultCode;
@@ -190,12 +191,13 @@
// Add a ReceiverInfo for a manifest receiver.
void schedule(@Nullable Intent intent, @Nullable ActivityInfo activityInfo,
@Nullable CompatibilityInfo compatInfo, int resultCode, @Nullable String data,
- @Nullable Bundle extras, boolean sync, int sendingUser, int processState,
- @Nullable BroadcastRecord r, int index) {
+ @Nullable Bundle extras, boolean sync, boolean assumeDelivered, int sendingUser,
+ int processState, @Nullable BroadcastRecord r, int index) {
ReceiverInfo ri = new ReceiverInfo();
ri.intent = intent;
ri.data = data;
ri.extras = extras;
+ ri.assumeDelivered = assumeDelivered;
ri.sendingUser = sendingUser;
ri.processState = processState;
ri.resultCode = resultCode;
@@ -214,10 +216,10 @@
*/
ArrayList<ReceiverInfo> registeredReceiver(@Nullable IIntentReceiver receiver,
@Nullable Intent intent, int resultCode, @Nullable String data,
- @Nullable Bundle extras, boolean ordered, boolean sticky,
+ @Nullable Bundle extras, boolean ordered, boolean sticky, boolean assumeDelivered,
int sendingUser, int processState) {
reset();
- schedule(receiver, intent, resultCode, data, extras, ordered, sticky,
+ schedule(receiver, intent, resultCode, data, extras, ordered, sticky, assumeDelivered,
sendingUser, processState, null, 0);
return receivers();
}
@@ -225,9 +227,9 @@
ArrayList<ReceiverInfo> manifestReceiver(@Nullable Intent intent,
@Nullable ActivityInfo activityInfo, @Nullable CompatibilityInfo compatInfo,
int resultCode, @Nullable String data, @Nullable Bundle extras, boolean sync,
- int sendingUser, int processState) {
+ boolean assumeDelivered, int sendingUser, int processState) {
reset();
- schedule(intent, activityInfo, compatInfo, resultCode, data, extras, sync,
+ schedule(intent, activityInfo, compatInfo, resultCode, data, extras, sync, assumeDelivered,
sendingUser, processState, null, 0);
return receivers();
}
@@ -255,6 +257,7 @@
n.intent = r.intent;
n.data = r.data;
n.extras = r.extras;
+ n.assumeDelivered = r.assumeDelivered;
n.sendingUser = r.sendingUser;
n.processState = r.processState;
n.resultCode = r.resultCode;
diff --git a/services/core/java/com/android/server/am/BroadcastRecord.java b/services/core/java/com/android/server/am/BroadcastRecord.java
index 1d4d425..9679fb8 100644
--- a/services/core/java/com/android/server/am/BroadcastRecord.java
+++ b/services/core/java/com/android/server/am/BroadcastRecord.java
@@ -88,6 +88,7 @@
final boolean interactive; // originated from user interaction?
final boolean initialSticky; // initial broadcast from register to sticky?
final boolean prioritized; // contains more than one priority tranche
+ final boolean deferUntilActive; // infinitely deferrable broadcast
final int userId; // user id this broadcast was for
final @Nullable String resolvedType; // the resolved data type
final @Nullable String[] requiredPermissions; // permissions the caller has required
@@ -97,6 +98,7 @@
final @Nullable BroadcastOptions options; // BroadcastOptions supplied by caller
final @NonNull List<Object> receivers; // contains BroadcastFilter and ResolveInfo
final @DeliveryState int[] delivery; // delivery state of each receiver
+ final boolean[] deferredUntilActive; // whether each receiver is infinitely deferred
final int[] blockedUntilTerminalCount; // blocked until count of each receiver
@Nullable ProcessRecord resultToApp; // who receives final result if non-null
@Nullable IIntentReceiver resultTo; // who receives final result if non-null
@@ -130,6 +132,7 @@
int manifestCount; // number of manifest receivers dispatched.
int manifestSkipCount; // number of manifest receivers skipped.
int terminalCount; // number of receivers in terminal state.
+ int deferredCount; // number of receivers in deferred state.
@Nullable BroadcastQueue queue; // the outbound queue handling this broadcast
// if set to true, app's process will be temporarily allowed to start activities from background
@@ -168,6 +171,8 @@
static final int DELIVERY_SCHEDULED = 4;
/** Terminal state: failure to dispatch */
static final int DELIVERY_FAILURE = 5;
+ /** Intermediate state: currently deferred while app is cached */
+ static final int DELIVERY_DEFERRED = 6;
@IntDef(flag = false, prefix = { "DELIVERY_" }, value = {
DELIVERY_PENDING,
@@ -176,6 +181,7 @@
DELIVERY_TIMEOUT,
DELIVERY_SCHEDULED,
DELIVERY_FAILURE,
+ DELIVERY_DEFERRED,
})
@Retention(RetentionPolicy.SOURCE)
public @interface DeliveryState {}
@@ -188,6 +194,7 @@
case DELIVERY_TIMEOUT: return "TIMEOUT";
case DELIVERY_SCHEDULED: return "SCHEDULED";
case DELIVERY_FAILURE: return "FAILURE";
+ case DELIVERY_DEFERRED: return "DEFERRED";
default: return Integer.toString(deliveryState);
}
}
@@ -388,6 +395,8 @@
options = _options;
receivers = (_receivers != null) ? _receivers : EMPTY_RECEIVERS;
delivery = new int[_receivers != null ? _receivers.size() : 0];
+ deferUntilActive = options != null ? options.isDeferUntilActive() : false;
+ deferredUntilActive = new boolean[deferUntilActive ? delivery.length : 0];
blockedUntilTerminalCount = calculateBlockedUntilTerminalCount(receivers, _serialized);
scheduledTime = new long[delivery.length];
terminalTime = new long[delivery.length];
@@ -443,6 +452,8 @@
options = from.options;
receivers = from.receivers;
delivery = from.delivery;
+ deferUntilActive = from.deferUntilActive;
+ deferredUntilActive = from.deferredUntilActive;
blockedUntilTerminalCount = from.blockedUntilTerminalCount;
scheduledTime = from.scheduledTime;
terminalTime = from.terminalTime;
@@ -606,7 +617,7 @@
*/
void setDeliveryState(int index, @DeliveryState int deliveryState) {
delivery[index] = deliveryState;
-
+ if (deferUntilActive) deferredUntilActive[index] = false;
switch (deliveryState) {
case DELIVERY_DELIVERED:
case DELIVERY_SKIPPED:
@@ -617,6 +628,9 @@
case DELIVERY_SCHEDULED:
scheduledTime[index] = SystemClock.uptimeMillis();
break;
+ case DELIVERY_DEFERRED:
+ if (deferUntilActive) deferredUntilActive[index] = true;
+ break;
}
}
@@ -647,6 +661,10 @@
return (intent.getFlags() & Intent.FLAG_RECEIVER_OFFLOAD) != 0;
}
+ boolean isDeferUntilActive() {
+ return deferUntilActive;
+ }
+
/**
* Core policy determination about this broadcast's delivery prioritization
*/
diff --git a/services/core/java/com/android/server/am/BroadcastSkipPolicy.java b/services/core/java/com/android/server/am/BroadcastSkipPolicy.java
index 481ab17..6718319 100644
--- a/services/core/java/com/android/server/am/BroadcastSkipPolicy.java
+++ b/services/core/java/com/android/server/am/BroadcastSkipPolicy.java
@@ -229,12 +229,7 @@
return "Background execution disabled: receiving "
+ r.intent + " to "
+ component.flattenToShortString();
- } else if (((r.intent.getFlags()&Intent.FLAG_RECEIVER_EXCLUDE_BACKGROUND) != 0)
- || (r.intent.getComponent() == null
- && r.intent.getPackage() == null
- && ((r.intent.getFlags()
- & Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND) == 0)
- && !isSignaturePerm(r.requiredPermissions))) {
+ } else if (disallowBackgroundStart(r)) {
mService.addBackgroundCheckViolationLocked(r.intent.getAction(),
component.getPackageName());
return "Background execution not allowed: receiving "
@@ -341,6 +336,18 @@
}
/**
+ * Determine if the given {@link BroadcastRecord} is eligible to launch processes.
+ */
+ public boolean disallowBackgroundStart(@NonNull BroadcastRecord r) {
+ return ((r.intent.getFlags() & Intent.FLAG_RECEIVER_EXCLUDE_BACKGROUND) != 0)
+ || (r.intent.getComponent() == null
+ && r.intent.getPackage() == null
+ && ((r.intent.getFlags()
+ & Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND) == 0)
+ && !isSignaturePerm(r.requiredPermissions));
+ }
+
+ /**
* Determine if the given {@link BroadcastRecord} is eligible to be sent to
* the given {@link BroadcastFilter}.
*
@@ -624,7 +631,7 @@
/**
* Return true if all given permissions are signature-only perms.
*/
- private boolean isSignaturePerm(String[] perms) {
+ private static boolean isSignaturePerm(String[] perms) {
if (perms == null) {
return false;
}
diff --git a/services/core/java/com/android/server/am/ForegroundServiceDelegation.java b/services/core/java/com/android/server/am/ForegroundServiceDelegation.java
index a051d17..a17848e 100644
--- a/services/core/java/com/android/server/am/ForegroundServiceDelegation.java
+++ b/services/core/java/com/android/server/am/ForegroundServiceDelegation.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.ForegroundServiceDelegationOptions;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
diff --git a/services/core/java/com/android/server/am/SameProcessApplicationThread.java b/services/core/java/com/android/server/am/SameProcessApplicationThread.java
index 62fd6e9..082e8e0 100644
--- a/services/core/java/com/android/server/am/SameProcessApplicationThread.java
+++ b/services/core/java/com/android/server/am/SameProcessApplicationThread.java
@@ -47,12 +47,12 @@
@Override
public void scheduleReceiver(Intent intent, ActivityInfo info, CompatibilityInfo compatInfo,
- int resultCode, String data, Bundle extras, boolean sync, int sendingUser,
- int processState) {
+ int resultCode, String data, Bundle extras, boolean ordered, boolean assumeDelivered,
+ int sendingUser, int processState) {
mHandler.post(() -> {
try {
- mWrapped.scheduleReceiver(intent, info, compatInfo, resultCode, data, extras, sync,
- sendingUser, processState);
+ mWrapped.scheduleReceiver(intent, info, compatInfo, resultCode, data, extras,
+ ordered, assumeDelivered, sendingUser, processState);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
@@ -61,12 +61,12 @@
@Override
public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent, int resultCode,
- String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser,
- int processState) {
+ String data, Bundle extras, boolean ordered, boolean sticky, boolean assumeDelivered,
+ int sendingUser, int processState) {
mHandler.post(() -> {
try {
mWrapped.scheduleRegisteredReceiver(receiver, intent, resultCode, data, extras,
- ordered, sticky, sendingUser, processState);
+ ordered, sticky, assumeDelivered, sendingUser, processState);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
@@ -79,11 +79,11 @@
ReceiverInfo r = info.get(i);
if (r.registered) {
scheduleRegisteredReceiver(r.receiver, r.intent,
- r.resultCode, r.data, r.extras, r.ordered, r.sticky,
+ r.resultCode, r.data, r.extras, r.ordered, r.sticky, r.assumeDelivered,
r.sendingUser, r.processState);
} else {
scheduleReceiver(r.intent, r.activityInfo, r.compatInfo,
- r.resultCode, r.data, r.extras, r.sync,
+ r.resultCode, r.data, r.extras, r.sync, r.assumeDelivered,
r.sendingUser, r.processState);
}
}
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 8c242743..def51b0 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -1063,7 +1063,7 @@
}
public AppBindRecord retrieveAppBindingLocked(Intent intent,
- ProcessRecord app) {
+ ProcessRecord app, ProcessRecord attributedApp) {
Intent.FilterComparison filter = new Intent.FilterComparison(intent);
IntentBindRecord i = bindings.get(filter);
if (i == null) {
@@ -1074,7 +1074,7 @@
if (a != null) {
return a;
}
- a = new AppBindRecord(this, i, app);
+ a = new AppBindRecord(this, i, app, attributedApp);
i.apps.put(app, a);
return a;
}
diff --git a/services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java b/services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java
index 5c18827..7d9b272 100644
--- a/services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java
+++ b/services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java
@@ -50,6 +50,8 @@
import com.android.server.infra.FrameworkResourcesServiceNameResolver;
import com.android.server.pm.KnownPackages;
+import com.google.android.collect.Sets;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -67,12 +69,10 @@
AmbientContextManagerPerUserService> {
private static final String TAG = AmbientContextManagerService.class.getSimpleName();
private static final String KEY_SERVICE_ENABLED = "service_enabled";
- private static final Set<Integer> DEFAULT_EVENT_SET = new HashSet<>(){{
- add(AmbientContextEvent.EVENT_COUGH);
- add(AmbientContextEvent.EVENT_SNORE);
- add(AmbientContextEvent.EVENT_BACK_DOUBLE_TAP);
- }
- };
+ private static final Set<Integer> DEFAULT_EVENT_SET = Sets.newHashSet(
+ AmbientContextEvent.EVENT_COUGH,
+ AmbientContextEvent.EVENT_SNORE,
+ AmbientContextEvent.EVENT_BACK_DOUBLE_TAP);
/** Default value in absence of {@link DeviceConfig} override. */
private static final boolean DEFAULT_SERVICE_ENABLED = true;
@@ -409,14 +409,6 @@
}
}
- private Set<Integer> intArrayToIntegerSet(int[] eventTypes) {
- Set<Integer> types = new HashSet<>();
- for (Integer i : eventTypes) {
- types.add(i);
- }
- return types;
- }
-
private AmbientContextManagerPerUserService.ServiceType getServiceType(String serviceName) {
final String wearableService = mContext.getResources()
.getString(R.string.config_defaultWearableSensingService);
@@ -513,6 +505,14 @@
return intArray;
}
+ private Set<Integer> intArrayToIntegerSet(int[] eventTypes) {
+ Set<Integer> types = new HashSet<>();
+ for (Integer i : eventTypes) {
+ types.add(i);
+ }
+ return types;
+ }
+
@NonNull
private static Integer[] intArrayToIntegerArray(@NonNull int[] integerSet) {
Integer[] intArray = new Integer[integerSet.length];
@@ -567,37 +567,24 @@
mContext.enforceCallingOrSelfPermission(
Manifest.permission.ACCESS_AMBIENT_CONTEXT_EVENT, TAG);
assertCalledByPackageOwner(packageName);
+
AmbientContextManagerPerUserService service =
getAmbientContextManagerPerUserServiceForEventTypes(
UserHandle.getCallingUserId(),
request.getEventTypes());
-
if (service == null) {
Slog.w(TAG, "onRegisterObserver unavailable user_id: "
+ UserHandle.getCallingUserId());
- }
-
- if (service.getServiceType() == ServiceType.DEFAULT && !mIsServiceEnabled) {
- Slog.d(TAG, "Service not available.");
- service.completeRegistration(observer,
- AmbientContextManager.STATUS_SERVICE_UNAVAILABLE);
- return;
- }
- if (service.getServiceType() == ServiceType.WEARABLE && !mIsWearableServiceEnabled) {
- Slog.d(TAG, "Wearable Service not available.");
- service.completeRegistration(observer,
- AmbientContextManager.STATUS_SERVICE_UNAVAILABLE);
- return;
- }
- if (containsMixedEvents(integerSetToIntArray(request.getEventTypes()))) {
- Slog.d(TAG, "AmbientContextEventRequest contains mixed events,"
- + " this is not supported.");
- service.completeRegistration(observer,
- AmbientContextManager.STATUS_NOT_SUPPORTED);
return;
}
- service.onRegisterObserver(request, packageName, observer);
+ int statusCode = checkStatusCode(
+ service, integerSetToIntArray(request.getEventTypes()));
+ if (statusCode == AmbientContextManager.STATUS_SUCCESS) {
+ service.onRegisterObserver(request, packageName, observer);
+ } else {
+ service.completeRegistration(observer, statusCode);
+ }
}
@Override
@@ -606,10 +593,10 @@
Manifest.permission.ACCESS_AMBIENT_CONTEXT_EVENT, TAG);
assertCalledByPackageOwner(callingPackage);
- AmbientContextManagerPerUserService service = null;
for (ClientRequest cr : mExistingClientRequests) {
if (cr.getPackageName().equals(callingPackage)) {
- service = getAmbientContextManagerPerUserServiceForEventTypes(
+ AmbientContextManagerPerUserService service =
+ getAmbientContextManagerPerUserServiceForEventTypes(
UserHandle.getCallingUserId(), cr.getRequest().getEventTypes());
if (service != null) {
service.onUnregisterObserver(callingPackage);
@@ -635,34 +622,18 @@
getAmbientContextManagerPerUserServiceForEventTypes(
UserHandle.getCallingUserId(), intArrayToIntegerSet(eventTypes));
if (service == null) {
- Slog.w(TAG, "onQueryServiceStatus unavailable user_id: "
+ Slog.w(TAG, "queryServiceStatus unavailable user_id: "
+ UserHandle.getCallingUserId());
- }
-
- if (service.getServiceType() == ServiceType.DEFAULT && !mIsServiceEnabled) {
- Slog.d(TAG, "Service not available.");
- service.sendStatusCallback(statusCallback,
- AmbientContextManager.STATUS_SERVICE_UNAVAILABLE);
- return;
- }
- if (service.getServiceType() == ServiceType.WEARABLE
- && !mIsWearableServiceEnabled) {
- Slog.d(TAG, "Wearable Service not available.");
- service.sendStatusCallback(statusCallback,
- AmbientContextManager.STATUS_SERVICE_UNAVAILABLE);
return;
}
- if (containsMixedEvents(eventTypes)) {
- Slog.d(TAG, "AmbientContextEventRequest contains mixed events,"
- + " this is not supported.");
- service.sendStatusCallback(statusCallback,
- AmbientContextManager.STATUS_NOT_SUPPORTED);
- return;
+ int statusCode = checkStatusCode(service, eventTypes);
+ if (statusCode == AmbientContextManager.STATUS_SUCCESS) {
+ service.onQueryServiceStatus(eventTypes, callingPackage,
+ statusCallback);
+ } else {
+ service.sendStatusCallback(statusCallback, statusCode);
}
-
- service.onQueryServiceStatus(eventTypes, callingPackage,
- statusCallback);
}
}
@@ -708,5 +679,22 @@
new AmbientContextShellCommand(AmbientContextManagerService.this).exec(
this, in, out, err, args, callback, resultReceiver);
}
+
+ private int checkStatusCode(AmbientContextManagerPerUserService service, int[] eventTypes) {
+ if (service.getServiceType() == ServiceType.DEFAULT && !mIsServiceEnabled) {
+ Slog.d(TAG, "Service not enabled.");
+ return AmbientContextManager.STATUS_SERVICE_UNAVAILABLE;
+ }
+ if (service.getServiceType() == ServiceType.WEARABLE && !mIsWearableServiceEnabled) {
+ Slog.d(TAG, "Wearable Service not available.");
+ return AmbientContextManager.STATUS_SERVICE_UNAVAILABLE;
+ }
+ if (containsMixedEvents(eventTypes)) {
+ Slog.d(TAG, "AmbientContextEventRequest contains mixed events,"
+ + " this is not supported.");
+ return AmbientContextManager.STATUS_NOT_SUPPORTED;
+ }
+ return AmbientContextManager.STATUS_SUCCESS;
+ }
}
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 78bff95..39c7f30 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -3717,9 +3717,11 @@
setRingerMode(getNewRingerMode(stream, index, flags),
TAG + ".onSetStreamVolume", false /*external*/);
}
- // setting non-zero volume for a muted stream unmutes the stream and vice versa,
+ // setting non-zero volume for a muted stream unmutes the stream and vice versa
+ // (only when changing volume for the current device),
// except for BT SCO stream where only explicit mute is allowed to comply to BT requirements
- if (streamType != AudioSystem.STREAM_BLUETOOTH_SCO) {
+ if ((streamType != AudioSystem.STREAM_BLUETOOTH_SCO)
+ && (getDeviceForStream(stream) == device)) {
mStreamStates[stream].mute(index == 0);
}
}
@@ -3783,12 +3785,13 @@
super.setVolumeIndexForAttributes_enforcePermission();
Objects.requireNonNull(attr, "attr must not be null");
- final int volumeGroup = getVolumeGroupIdForAttributes(attr);
+ int volumeGroup = AudioProductStrategy.getVolumeGroupIdForAudioAttributes(
+ attr, /* fallbackOnDefault= */false);
if (sVolumeGroupStates.indexOfKey(volumeGroup) < 0) {
Log.e(TAG, ": no volume group found for attributes " + attr.toString());
return;
}
- final VolumeGroupState vgs = sVolumeGroupStates.get(volumeGroup);
+ VolumeGroupState vgs = sVolumeGroupStates.get(volumeGroup);
sVolumeLogger.enqueue(new VolumeEvent(VolumeEvent.VOL_SET_GROUP_VOL, attr, vgs.name(),
index/*val1*/, flags/*val2*/, callingPackage));
@@ -3796,7 +3799,7 @@
vgs.setVolumeIndex(index, flags);
// For legacy reason, propagate to all streams associated to this volume group
- for (final int groupedStream : vgs.getLegacyStreamTypes()) {
+ for (int groupedStream : vgs.getLegacyStreamTypes()) {
try {
ensureValidStreamType(groupedStream);
} catch (IllegalArgumentException e) {
@@ -3828,7 +3831,9 @@
super.getVolumeIndexForAttributes_enforcePermission();
Objects.requireNonNull(attr, "attr must not be null");
- final int volumeGroup = getVolumeGroupIdForAttributes(attr);
+ final int volumeGroup =
+ AudioProductStrategy.getVolumeGroupIdForAudioAttributes(
+ attr, /* fallbackOnDefault= */false);
if (sVolumeGroupStates.indexOfKey(volumeGroup) < 0) {
throw new IllegalArgumentException("No volume group for attributes " + attr);
}
@@ -4378,31 +4383,6 @@
sendVolumeUpdate(streamType, oldIndex, index, flags, device);
}
-
-
- private int getVolumeGroupIdForAttributes(@NonNull AudioAttributes attributes) {
- Objects.requireNonNull(attributes, "attributes must not be null");
- int volumeGroupId = getVolumeGroupIdForAttributesInt(attributes);
- if (volumeGroupId != AudioVolumeGroup.DEFAULT_VOLUME_GROUP) {
- return volumeGroupId;
- }
- // The default volume group is the one hosted by default product strategy, i.e.
- // supporting Default Attributes
- return getVolumeGroupIdForAttributesInt(AudioProductStrategy.getDefaultAttributes());
- }
-
- private int getVolumeGroupIdForAttributesInt(@NonNull AudioAttributes attributes) {
- Objects.requireNonNull(attributes, "attributes must not be null");
- for (final AudioProductStrategy productStrategy :
- AudioProductStrategy.getAudioProductStrategies()) {
- int volumeGroupId = productStrategy.getVolumeGroupIdForAudioAttributes(attributes);
- if (volumeGroupId != AudioVolumeGroup.DEFAULT_VOLUME_GROUP) {
- return volumeGroupId;
- }
- }
- return AudioVolumeGroup.DEFAULT_VOLUME_GROUP;
- }
-
private void dispatchAbsoluteVolumeChanged(int streamType, AbsoluteVolumeDeviceInfo deviceInfo,
int index) {
VolumeInfo volumeInfo = deviceInfo.getMatchingVolumeInfoForStream(streamType);
@@ -4435,7 +4415,6 @@
}
}
-
// No ringer or zen muted stream volumes can be changed unless it'll exit dnd
private boolean volumeAdjustmentAllowedByDnd(int streamTypeAlias, int flags) {
switch (mNm.getZenMode()) {
diff --git a/services/core/java/com/android/server/audio/SoundDoseHelper.java b/services/core/java/com/android/server/audio/SoundDoseHelper.java
index 7edd911..919b850 100644
--- a/services/core/java/com/android/server/audio/SoundDoseHelper.java
+++ b/services/core/java/com/android/server/audio/SoundDoseHelper.java
@@ -202,15 +202,7 @@
}
}
mCurrentCsd = currentCsd;
- mDoseRecords.addAll(Arrays.asList(records));
- long totalDuration = 0;
- for (SoundDoseRecord record : records) {
- Log.i(TAG, " new record: csd=" + record.value
- + " averageMel=" + record.averageMel + " timestamp=" + record.timestamp
- + " duration=" + record.duration);
- totalDuration += record.duration;
- }
- mLogger.enqueue(SoundDoseEvent.getDoseUpdateEvent(currentCsd, totalDuration));
+ updateSoundDoseRecords(records, currentCsd);
}
};
@@ -626,6 +618,29 @@
return null;
}
+ private void updateSoundDoseRecords(SoundDoseRecord[] newRecords, float currentCsd) {
+ long totalDuration = 0;
+ for (SoundDoseRecord record : newRecords) {
+ Log.i(TAG, " new record: " + record);
+ totalDuration += record.duration;
+
+ if (record.value < 0) {
+ // Negative value means the record timestamp exceeded the CSD rolling window size
+ // and needs to be removed
+ if (!mDoseRecords.removeIf(
+ r -> r.value == -record.value && r.timestamp == record.timestamp
+ && r.averageMel == record.averageMel
+ && r.duration == record.duration)) {
+ Log.w(TAG, "Could not find cached record to remove: " + record);
+ }
+ } else {
+ mDoseRecords.add(record);
+ }
+ }
+
+ mLogger.enqueue(SoundDoseEvent.getDoseUpdateEvent(currentCsd, totalDuration));
+ }
+
// StreamVolumeCommand contains the information needed to defer the process of
// setStreamVolume() in case the user has to acknowledge the safe volume warning message.
private static class StreamVolumeCommand {
diff --git a/services/core/java/com/android/server/backup/SystemBackupAgent.java b/services/core/java/com/android/server/backup/SystemBackupAgent.java
index 1b20e43..59d8afa 100644
--- a/services/core/java/com/android/server/backup/SystemBackupAgent.java
+++ b/services/core/java/com/android/server/backup/SystemBackupAgent.java
@@ -84,7 +84,8 @@
private static final String WALLPAPER_IMAGE_KEY = WallpaperBackupHelper.WALLPAPER_IMAGE_KEY;
private static final Set<String> sEligibleForMultiUser = Sets.newArraySet(
- PERMISSION_HELPER, NOTIFICATION_HELPER, SYNC_SETTINGS_HELPER, APP_LOCALES_HELPER);
+ PERMISSION_HELPER, NOTIFICATION_HELPER, SYNC_SETTINGS_HELPER, APP_LOCALES_HELPER,
+ ACCOUNT_MANAGER_HELPER);
private int mUserId = UserHandle.USER_SYSTEM;
@@ -100,7 +101,7 @@
addHelper(PERMISSION_HELPER, new PermissionBackupHelper(mUserId));
addHelper(USAGE_STATS_HELPER, new UsageStatsBackupHelper(this));
addHelper(SHORTCUT_MANAGER_HELPER, new ShortcutBackupHelper());
- addHelper(ACCOUNT_MANAGER_HELPER, new AccountManagerBackupHelper());
+ addHelper(ACCOUNT_MANAGER_HELPER, new AccountManagerBackupHelper(mUserId));
addHelper(SLICES_HELPER, new SliceBackupHelper(this));
addHelper(PEOPLE_HELPER, new PeopleBackupHelper(mUserId));
addHelper(APP_LOCALES_HELPER, new AppSpecificLocalesBackupHelper(mUserId));
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
index cb409fe..0248010 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
@@ -125,7 +125,7 @@
return proto.getBytes();
}
- @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_BIOMETRIC)
+ @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@Override // Binder call
public List<FaceSensorPropertiesInternal> getSensorPropertiesInternal(
String opPackageName) {
diff --git a/services/core/java/com/android/server/broadcastradio/aidl/ProgramInfoCache.java b/services/core/java/com/android/server/broadcastradio/aidl/ProgramInfoCache.java
index 39b1354..c9ae735 100644
--- a/services/core/java/com/android/server/broadcastradio/aidl/ProgramInfoCache.java
+++ b/services/core/java/com/android/server/broadcastradio/aidl/ProgramInfoCache.java
@@ -86,12 +86,8 @@
}
@VisibleForTesting
- boolean programInfosAreExactly(RadioManager.ProgramInfo... programInfos) {
- Map<ProgramSelector.Identifier, RadioManager.ProgramInfo> expectedMap = new ArrayMap<>();
- for (int i = 0; i < programInfos.length; i++) {
- expectedMap.put(programInfos[i].getSelector().getPrimaryId(), programInfos[i]);
- }
- return expectedMap.equals(mProgramInfoMap);
+ List<RadioManager.ProgramInfo> toProgramInfoList() {
+ return new ArrayList<>(mProgramInfoMap.values());
}
@Override
diff --git a/services/core/java/com/android/server/hdmi/Constants.java b/services/core/java/com/android/server/hdmi/Constants.java
index 6b5af88..6d1af3b 100644
--- a/services/core/java/com/android/server/hdmi/Constants.java
+++ b/services/core/java/com/android/server/hdmi/Constants.java
@@ -19,6 +19,8 @@
import android.annotation.IntDef;
import android.annotation.StringDef;
import android.hardware.hdmi.HdmiDeviceInfo;
+import android.hardware.tv.hdmi.connection.HpdSignal;
+import android.hardware.tv.hdmi.earc.IEArcStatus;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -599,10 +601,13 @@
})
@interface RcProfileSource {}
- static final int HDMI_EARC_STATUS_IDLE = 0; // IDLE1
- static final int HDMI_EARC_STATUS_EARC_PENDING = 1; // DISC1 and DISC2
- static final int HDMI_EARC_STATUS_ARC_PENDING = 2; // IDLE2 for ARC
- static final int HDMI_EARC_STATUS_EARC_CONNECTED = 3; // eARC connected
+ static final int HDMI_EARC_STATUS_IDLE = IEArcStatus.STATUS_IDLE; // IDLE1
+ static final int HDMI_EARC_STATUS_EARC_PENDING =
+ IEArcStatus.STATUS_EARC_PENDING; // DISC1 and DISC2
+ static final int HDMI_EARC_STATUS_ARC_PENDING = IEArcStatus.STATUS_ARC_PENDING; // IDLE2 for ARC
+ static final int HDMI_EARC_STATUS_EARC_CONNECTED =
+ IEArcStatus.STATUS_EARC_CONNECTED; // eARC connected
+
@IntDef({
HDMI_EARC_STATUS_IDLE,
HDMI_EARC_STATUS_EARC_PENDING,
@@ -611,8 +616,11 @@
})
@interface EarcStatus {}
- static final int HDMI_HPD_TYPE_PHYSICAL = 0; // Default. Physical hotplug signal.
- static final int HDMI_HPD_TYPE_STATUS_BIT = 1; // HDMI_HPD status bit.
+ static final int HDMI_HPD_TYPE_PHYSICAL =
+ HpdSignal.HDMI_HPD_PHYSICAL; // Default. Physical hotplug signal.
+ static final int HDMI_HPD_TYPE_STATUS_BIT =
+ HpdSignal.HDMI_HPD_STATUS_BIT; // HDMI_HPD status bit.
+
@IntDef({
HDMI_HPD_TYPE_PHYSICAL,
HDMI_HPD_TYPE_STATUS_BIT
@@ -620,6 +628,12 @@
@interface HpdSignalType {}
static final String DEVICE_CONFIG_FEATURE_FLAG_SOUNDBAR_MODE = "soundbar_mode";
+ static final String DEVICE_CONFIG_FEATURE_FLAG_ENABLE_EARC_TX = "enable_earc_tx";
+ @StringDef({
+ DEVICE_CONFIG_FEATURE_FLAG_SOUNDBAR_MODE,
+ DEVICE_CONFIG_FEATURE_FLAG_ENABLE_EARC_TX
+ })
+ @interface FeatureFlag {}
private Constants() {
/* cannot be instantiated */
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index f6566d8..14b9121 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -18,6 +18,7 @@
import static android.hardware.hdmi.HdmiControlManager.DEVICE_EVENT_ADD_DEVICE;
import static android.hardware.hdmi.HdmiControlManager.DEVICE_EVENT_REMOVE_DEVICE;
+import static android.hardware.hdmi.HdmiControlManager.EARC_FEATURE_DISABLED;
import static android.hardware.hdmi.HdmiControlManager.EARC_FEATURE_ENABLED;
import static android.hardware.hdmi.HdmiControlManager.HDMI_CEC_CONTROL_ENABLED;
import static android.hardware.hdmi.HdmiControlManager.SOUNDBAR_MODE_DISABLED;
@@ -454,6 +455,9 @@
private boolean mSoundbarModeFeatureFlagEnabled = false;
@ServiceThreadOnly
+ private boolean mEarcTxFeatureFlagEnabled = false;
+
+ @ServiceThreadOnly
private int mActivePortId = Constants.INVALID_PORT_ID;
// Set to true while the input change by MHL is allowed.
@@ -666,9 +670,18 @@
setProhibitMode(false);
mHdmiControlEnabled = mHdmiCecConfig.getIntValue(
HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED);
+
+ mSoundbarModeFeatureFlagEnabled = mDeviceConfig.getBoolean(
+ Constants.DEVICE_CONFIG_FEATURE_FLAG_SOUNDBAR_MODE, false);
+ mEarcTxFeatureFlagEnabled = mDeviceConfig.getBoolean(
+ Constants.DEVICE_CONFIG_FEATURE_FLAG_ENABLE_EARC_TX, false);
+
synchronized (mLock) {
mEarcEnabled = (mHdmiCecConfig.getIntValue(
HdmiControlManager.SETTING_NAME_EARC_ENABLED) == EARC_FEATURE_ENABLED);
+ if (isTvDevice()) {
+ mEarcEnabled &= mEarcTxFeatureFlagEnabled;
+ }
}
setHdmiCecVolumeControlEnabledInternal(getHdmiCecConfig().getIntValue(
HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE));
@@ -812,20 +825,42 @@
}
}
}, mServiceThreadExecutor);
+
+ if (isTvDevice()) {
+ mDeviceConfig.addOnPropertiesChangedListener(getContext().getMainExecutor(),
+ new DeviceConfig.OnPropertiesChangedListener() {
+ @Override
+ public void onPropertiesChanged(DeviceConfig.Properties properties) {
+ mEarcTxFeatureFlagEnabled = properties.getBoolean(
+ Constants.DEVICE_CONFIG_FEATURE_FLAG_ENABLE_EARC_TX,
+ false);
+ boolean earcEnabledSetting = mHdmiCecConfig.getIntValue(
+ HdmiControlManager.SETTING_NAME_EARC_ENABLED)
+ == EARC_FEATURE_ENABLED;
+ setEarcEnabled(earcEnabledSetting && mEarcTxFeatureFlagEnabled
+ ? EARC_FEATURE_ENABLED : EARC_FEATURE_DISABLED);
+ }
+ });
+ }
+
mHdmiCecConfig.registerChangeListener(HdmiControlManager.SETTING_NAME_EARC_ENABLED,
new HdmiCecConfig.SettingChangeListener() {
@Override
public void onChange(String setting) {
- @HdmiControlManager.HdmiCecControl int enabled = mHdmiCecConfig.getIntValue(
- HdmiControlManager.SETTING_NAME_EARC_ENABLED);
- setEarcEnabled(enabled);
+ if (isTvDevice()) {
+ boolean earcEnabledSetting = mHdmiCecConfig.getIntValue(
+ HdmiControlManager.SETTING_NAME_EARC_ENABLED)
+ == EARC_FEATURE_ENABLED;
+ setEarcEnabled(earcEnabledSetting && mEarcTxFeatureFlagEnabled
+ ? EARC_FEATURE_ENABLED : EARC_FEATURE_DISABLED);
+ } else {
+ setEarcEnabled(mHdmiCecConfig.getIntValue(
+ HdmiControlManager.SETTING_NAME_EARC_ENABLED));
+ }
}
},
mServiceThreadExecutor);
- mSoundbarModeFeatureFlagEnabled = mDeviceConfig.getBoolean(
- Constants.DEVICE_CONFIG_FEATURE_FLAG_SOUNDBAR_MODE, false);
-
mDeviceConfig.addOnPropertiesChangedListener(getContext().getMainExecutor(),
new DeviceConfig.OnPropertiesChangedListener() {
@Override
@@ -896,6 +931,11 @@
}
@VisibleForTesting
+ void setEarcController(HdmiEarcController earcController) {
+ mEarcController = earcController;
+ }
+
+ @VisibleForTesting
void setHdmiCecNetwork(HdmiCecNetwork hdmiCecNetwork) {
mHdmiCecNetwork = hdmiCecNetwork;
}
@@ -4564,6 +4604,11 @@
startArcAction(false, new IHdmiControlCallback.Stub() {
@Override
public void onComplete(int result) throws RemoteException {
+ if (result != HdmiControlManager.RESULT_SUCCESS) {
+ Slog.w(TAG,
+ "ARC termination before enabling eARC in the HAL failed with "
+ + "result: " + result);
+ }
// Independently of the result (i.e. independently of whether the ARC RX device
// responded with <Terminate ARC> or not), we always end up terminating ARC in
// the HAL. As soon as we do that, we can enable eARC in the HAL.
diff --git a/services/core/java/com/android/server/hdmi/HdmiEarcController.java b/services/core/java/com/android/server/hdmi/HdmiEarcController.java
index 8522509..2bb9ffb 100644
--- a/services/core/java/com/android/server/hdmi/HdmiEarcController.java
+++ b/services/core/java/com/android/server/hdmi/HdmiEarcController.java
@@ -16,8 +16,14 @@
package com.android.server.hdmi;
+import android.hardware.tv.hdmi.earc.IEArc;
+import android.hardware.tv.hdmi.earc.IEArcCallback;
import android.os.Handler;
+import android.os.IBinder;
import android.os.Looper;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.ServiceSpecificException;
import com.android.internal.annotations.VisibleForTesting;
@@ -29,9 +35,109 @@
private final HdmiControlService mService;
+ private EArcNativeWrapper mEArcNativeWrapperImpl;
+
+ protected interface EArcNativeWrapper {
+ boolean nativeInit();
+ void nativeSetEArcEnabled(boolean enabled);
+ boolean nativeIsEArcEnabled();
+ void nativeSetCallback(EarcAidlCallback callback);
+ byte nativeGetState(int portId);
+ byte[] nativeGetLastReportedAudioCapabilities(int portId);
+ }
+
+ private static final class EArcNativeWrapperImpl implements EArcNativeWrapper,
+ IBinder.DeathRecipient {
+ private IEArc mEArc;
+ private EarcAidlCallback mEArcCallback;
+
+ @Override
+ public void binderDied() {
+ mEArc.asBinder().unlinkToDeath(this, 0);
+ connectToHal();
+ if (mEArcCallback != null) {
+ nativeSetCallback(mEArcCallback);
+ }
+ }
+
+ boolean connectToHal() {
+ mEArc =
+ IEArc.Stub.asInterface(
+ ServiceManager.getService(IEArc.DESCRIPTOR + "/default"));
+ if (mEArc == null) {
+ return false;
+ }
+ try {
+ mEArc.asBinder().linkToDeath(this, 0);
+ } catch (RemoteException e) {
+ HdmiLogger.error("Couldn't link callback object: ", e);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean nativeInit() {
+ return connectToHal();
+ }
+
+ @Override
+ public void nativeSetEArcEnabled(boolean enabled) {
+ try {
+ mEArc.setEArcEnabled(enabled);
+ } catch (ServiceSpecificException sse) {
+ HdmiLogger.error(
+ "Could not set eARC enabled to " + enabled + ". Error: ", sse.errorCode);
+ } catch (RemoteException re) {
+ HdmiLogger.error("Could not set eARC enabled to " + enabled + ":. Exception: ", re);
+ }
+ }
+
+ @Override
+ public boolean nativeIsEArcEnabled() {
+ try {
+ return mEArc.isEArcEnabled();
+ } catch (RemoteException re) {
+ HdmiLogger.error("Could not read if eARC is enabled. Exception: ", re);
+ return false;
+ }
+ }
+
+ @Override
+ public void nativeSetCallback(EarcAidlCallback callback) {
+ mEArcCallback = callback;
+ try {
+ mEArc.setCallback(callback);
+ } catch (RemoteException re) {
+ HdmiLogger.error("Could not set callback. Exception: ", re);
+ }
+ }
+
+ @Override
+ public byte nativeGetState(int portId) {
+ try {
+ return mEArc.getState(portId);
+ } catch (RemoteException re) {
+ HdmiLogger.error("Could not get eARC state. Exception: ", re);
+ return -1;
+ }
+ }
+
+ @Override
+ public byte[] nativeGetLastReportedAudioCapabilities(int portId) {
+ try {
+ return mEArc.getLastReportedAudioCapabilities(portId);
+ } catch (RemoteException re) {
+ HdmiLogger.error(
+ "Could not read last reported audio capabilities. Exception: ", re);
+ return null;
+ }
+ }
+ }
+
// Private constructor. Use HdmiEarcController.create().
- private HdmiEarcController(HdmiControlService service) {
+ private HdmiEarcController(HdmiControlService service, EArcNativeWrapper nativeWrapper) {
mService = service;
+ mEArcNativeWrapperImpl = nativeWrapper;
}
/**
@@ -45,14 +151,29 @@
* returns {@code null}.
*/
static HdmiEarcController create(HdmiControlService service) {
- // TODO add the native wrapper and return null if eARC HAL is not present.
- HdmiEarcController controller = new HdmiEarcController(service);
- controller.init();
+ return createWithNativeWrapper(service, new EArcNativeWrapperImpl());
+ }
+
+ /**
+ * A factory method with injection of native methods for testing.
+ */
+ static HdmiEarcController createWithNativeWrapper(HdmiControlService service,
+ EArcNativeWrapper nativeWrapper) {
+ HdmiEarcController controller = new HdmiEarcController(service, nativeWrapper);
+ if (!controller.init(nativeWrapper)) {
+ HdmiLogger.warning("Could not connect to eARC AIDL HAL.");
+ return null;
+ }
return controller;
}
- private void init() {
- mControlHandler = new Handler(mService.getServiceLooper());
+ private boolean init(EArcNativeWrapper nativeWrapper) {
+ if (nativeWrapper.nativeInit()) {
+ mControlHandler = new Handler(mService.getServiceLooper());
+ mEArcNativeWrapperImpl.nativeSetCallback(new EarcAidlCallback());
+ return true;
+ }
+ return false;
}
private void assertRunOnServiceThread() {
@@ -73,9 +194,7 @@
@HdmiAnnotations.ServiceThreadOnly
void setEarcEnabled(boolean enabled) {
assertRunOnServiceThread();
- // Stub.
- // TODO: bind to native.
- // TODO: handle error return values here, with logging.
+ mEArcNativeWrapperImpl.nativeSetEArcEnabled(enabled);
}
/**
@@ -86,23 +205,21 @@
@HdmiAnnotations.ServiceThreadOnly
@Constants.EarcStatus
int getState(int portId) {
- // Stub.
- // TODO: bind to native.
- return Constants.HDMI_EARC_STATUS_IDLE;
+ return mEArcNativeWrapperImpl.nativeGetState(portId);
}
- /**
+ /**
* Ask the HAL to report the last eARC capabilities that the connected audio system reported.
+ *
* @return the raw eARC capabilities
*/
@HdmiAnnotations.ServiceThreadOnly
- byte[] getLastReportedCaps() {
- // Stub. TODO: bind to native.
- return new byte[] {};
+ byte[] getLastReportedCaps(int portId) {
+ return mEArcNativeWrapperImpl.nativeGetLastReportedAudioCapabilities(portId);
}
- final class EarcCallback {
- public void onStateChange(@Constants.EarcStatus int status, int portId) {
+ final class EarcAidlCallback extends IEArcCallback.Stub {
+ public void onStateChange(@Constants.EarcStatus byte status, int portId) {
runOnServiceThread(
() -> mService.handleEarcStateChange(status, portId));
}
@@ -111,7 +228,15 @@
runOnServiceThread(
() -> mService.handleEarcCapabilitiesReported(rawCapabilities, portId));
}
- }
- // TODO: bind to native.
+ @Override
+ public synchronized String getInterfaceHash() throws RemoteException {
+ return IEArcCallback.Stub.HASH;
+ }
+
+ @Override
+ public int getInterfaceVersion() throws RemoteException {
+ return IEArcCallback.Stub.VERSION;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/input/BatteryController.java b/services/core/java/com/android/server/input/BatteryController.java
index c99a7a0..993b4fd 100644
--- a/services/core/java/com/android/server/input/BatteryController.java
+++ b/services/core/java/com/android/server/input/BatteryController.java
@@ -31,6 +31,7 @@
import android.hardware.input.IInputDeviceBatteryState;
import android.hardware.input.InputManager;
import android.os.Handler;
+import android.os.HandlerExecutor;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
@@ -51,6 +52,7 @@
import java.util.Arrays;
import java.util.Objects;
import java.util.Set;
+import java.util.concurrent.Executor;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
@@ -102,7 +104,7 @@
BatteryController(Context context, NativeInputManagerService nativeService, Looper looper) {
this(context, nativeService, looper, new UEventManager() {},
- new LocalBluetoothBatteryManager(context));
+ new LocalBluetoothBatteryManager(context, looper));
}
@VisibleForTesting
@@ -163,7 +165,7 @@
// This is the first listener that is monitoring this device.
monitor = new DeviceMonitor(deviceId);
mDeviceMonitors.put(deviceId, monitor);
- updateBluetoothMonitoring();
+ updateBluetoothBatteryMonitoring();
}
if (DEBUG) {
@@ -378,13 +380,26 @@
}
}
- private void handleBluetoothBatteryLevelChange(long eventTime, String address) {
+ private void handleBluetoothBatteryLevelChange(long eventTime, String address,
+ int batteryLevel) {
synchronized (mLock) {
final DeviceMonitor monitor = findIf(mDeviceMonitors, (m) ->
(m.mBluetoothDevice != null
&& address.equals(m.mBluetoothDevice.getAddress())));
if (monitor != null) {
- monitor.onBluetoothBatteryChanged(eventTime);
+ monitor.onBluetoothBatteryChanged(eventTime, batteryLevel);
+ }
+ }
+ }
+
+ private void handleBluetoothMetadataChange(@NonNull BluetoothDevice device, int key,
+ @Nullable byte[] value) {
+ synchronized (mLock) {
+ final DeviceMonitor monitor =
+ findIf(mDeviceMonitors, (m) -> device.equals(m.mBluetoothDevice));
+ if (monitor != null) {
+ final long eventTime = SystemClock.uptimeMillis();
+ monitor.onBluetoothMetadataChanged(eventTime, key, value);
}
}
}
@@ -514,31 +529,19 @@
isPresent ? mNative.getBatteryCapacity(deviceId) / 100.f : Float.NaN);
}
- // Queries the battery state of an input device from Bluetooth.
- private State queryBatteryStateFromBluetooth(int deviceId, long updateTime,
- @NonNull BluetoothDevice bluetoothDevice) {
- final int level = mBluetoothBatteryManager.getBatteryLevel(bluetoothDevice.getAddress());
- if (level == BluetoothDevice.BATTERY_LEVEL_BLUETOOTH_OFF
- || level == BluetoothDevice.BATTERY_LEVEL_UNKNOWN) {
- return new State(deviceId);
- }
- return new State(deviceId, updateTime, true /*isPresent*/, BatteryState.STATUS_UNKNOWN,
- level / 100.f);
- }
-
- private void updateBluetoothMonitoring() {
+ private void updateBluetoothBatteryMonitoring() {
synchronized (mLock) {
if (anyOf(mDeviceMonitors, (m) -> m.mBluetoothDevice != null)) {
// At least one input device being monitored is connected over Bluetooth.
if (mBluetoothBatteryListener == null) {
if (DEBUG) Slog.d(TAG, "Registering bluetooth battery listener");
mBluetoothBatteryListener = this::handleBluetoothBatteryLevelChange;
- mBluetoothBatteryManager.addListener(mBluetoothBatteryListener);
+ mBluetoothBatteryManager.addBatteryListener(mBluetoothBatteryListener);
}
} else if (mBluetoothBatteryListener != null) {
// No Bluetooth input devices are monitored, so remove the registered listener.
if (DEBUG) Slog.d(TAG, "Unregistering bluetooth battery listener");
- mBluetoothBatteryManager.removeListener(mBluetoothBatteryListener);
+ mBluetoothBatteryManager.removeBatteryListener(mBluetoothBatteryListener);
mBluetoothBatteryListener = null;
}
}
@@ -550,16 +553,23 @@
// Represents whether the input device has a sysfs battery node.
protected boolean mHasBattery = false;
- protected final State mBluetoothState;
@Nullable
private BluetoothDevice mBluetoothDevice;
+ long mBluetoothEventTime = 0;
+ // The battery level reported by the Bluetooth Hands-Free Profile (HPF) obtained through
+ // BluetoothDevice#getBatteryLevel().
+ int mBluetoothBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
+ // The battery level and status reported through the Bluetooth device's metadata.
+ int mBluetoothMetadataBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
+ int mBluetoothMetadataBatteryStatus = BatteryState.STATUS_UNKNOWN;
+ @Nullable
+ private BluetoothAdapter.OnMetadataChangedListener mBluetoothMetadataListener;
@Nullable
private UEventBatteryListener mUEventBatteryListener;
DeviceMonitor(int deviceId) {
mState = new State(deviceId);
- mBluetoothState = new State(deviceId);
// Load the initial battery state and start monitoring.
final long eventTime = SystemClock.uptimeMillis();
@@ -570,7 +580,7 @@
final State oldState = getBatteryStateForReporting();
changes.accept(eventTime);
final State newState = getBatteryStateForReporting();
- if (!oldState.equals(newState)) {
+ if (!oldState.equalsIgnoringUpdateTime(newState)) {
notifyAllListenersForDevice(newState);
}
}
@@ -594,13 +604,22 @@
final BluetoothDevice bluetoothDevice = getBluetoothDevice(deviceId);
if (!Objects.equals(mBluetoothDevice, bluetoothDevice)) {
if (DEBUG) {
- Slog.d(TAG, "Bluetooth device "
- + ((bluetoothDevice != null) ? "is" : "is not")
- + " now present for deviceId " + deviceId);
+ Slog.d(TAG, "Bluetooth device is now "
+ + ((bluetoothDevice != null) ? "" : "not")
+ + " present for deviceId " + deviceId);
}
+
+ mBluetoothBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
+ stopBluetoothMetadataMonitoring();
+
mBluetoothDevice = bluetoothDevice;
- updateBluetoothMonitoring();
- updateBatteryStateFromBluetooth(eventTime);
+ updateBluetoothBatteryMonitoring();
+
+ if (mBluetoothDevice != null) {
+ mBluetoothBatteryLevel = mBluetoothBatteryManager.getBatteryLevel(
+ mBluetoothDevice.getAddress());
+ startBluetoothMetadataMonitoring(eventTime);
+ }
}
}
@@ -632,11 +651,39 @@
}
}
+ private void startBluetoothMetadataMonitoring(long eventTime) {
+ Objects.requireNonNull(mBluetoothDevice);
+
+ mBluetoothMetadataListener = BatteryController.this::handleBluetoothMetadataChange;
+ mBluetoothBatteryManager.addMetadataListener(mBluetoothDevice.getAddress(),
+ mBluetoothMetadataListener);
+ updateBluetoothMetadataState(eventTime, BluetoothDevice.METADATA_MAIN_BATTERY,
+ mBluetoothBatteryManager.getMetadata(mBluetoothDevice.getAddress(),
+ BluetoothDevice.METADATA_MAIN_BATTERY));
+ updateBluetoothMetadataState(eventTime, BluetoothDevice.METADATA_MAIN_CHARGING,
+ mBluetoothBatteryManager.getMetadata(mBluetoothDevice.getAddress(),
+ BluetoothDevice.METADATA_MAIN_CHARGING));
+ }
+
+ private void stopBluetoothMetadataMonitoring() {
+ if (mBluetoothMetadataListener == null) {
+ return;
+ }
+ Objects.requireNonNull(mBluetoothDevice);
+
+ mBluetoothBatteryManager.removeMetadataListener(
+ mBluetoothDevice.getAddress(), mBluetoothMetadataListener);
+ mBluetoothMetadataListener = null;
+ mBluetoothMetadataBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
+ mBluetoothMetadataBatteryStatus = BatteryState.STATUS_UNKNOWN;
+ }
+
// This must be called when the device is no longer being monitored.
public void onMonitorDestroy() {
stopNativeMonitoring();
+ stopBluetoothMetadataMonitoring();
mBluetoothDevice = null;
- updateBluetoothMonitoring();
+ updateBluetoothBatteryMonitoring();
}
protected void updateBatteryStateFromNative(long eventTime) {
@@ -644,13 +691,6 @@
queryBatteryStateFromNative(mState.deviceId, eventTime, mHasBattery));
}
- protected void updateBatteryStateFromBluetooth(long eventTime) {
- final State bluetoothState = mBluetoothDevice == null ? new State(mState.deviceId)
- : queryBatteryStateFromBluetooth(mState.deviceId, eventTime,
- mBluetoothDevice);
- mBluetoothState.updateIfChanged(bluetoothState);
- }
-
public void onPoll(long eventTime) {
processChangesAndNotify(eventTime, this::updateBatteryStateFromNative);
}
@@ -659,8 +699,51 @@
processChangesAndNotify(eventTime, this::updateBatteryStateFromNative);
}
- public void onBluetoothBatteryChanged(long eventTime) {
- processChangesAndNotify(eventTime, this::updateBatteryStateFromBluetooth);
+ public void onBluetoothBatteryChanged(long eventTime, int bluetoothBatteryLevel) {
+ processChangesAndNotify(eventTime, (time) -> {
+ mBluetoothBatteryLevel = bluetoothBatteryLevel;
+ mBluetoothEventTime = time;
+ });
+ }
+
+ public void onBluetoothMetadataChanged(long eventTime, int key, @Nullable byte[] value) {
+ processChangesAndNotify(eventTime,
+ (time) -> updateBluetoothMetadataState(time, key, value));
+ }
+
+ private void updateBluetoothMetadataState(long eventTime, int key,
+ @Nullable byte[] value) {
+ switch (key) {
+ case BluetoothDevice.METADATA_MAIN_BATTERY:
+ mBluetoothEventTime = eventTime;
+ mBluetoothMetadataBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
+ if (value != null) {
+ try {
+ mBluetoothMetadataBatteryLevel = Integer.parseInt(
+ new String(value));
+ } catch (NumberFormatException e) {
+ Slog.wtf(TAG,
+ "Failed to parse bluetooth METADATA_MAIN_BATTERY with "
+ + "value '"
+ + new String(value) + "' for device "
+ + mBluetoothDevice);
+ }
+ }
+ break;
+ case BluetoothDevice.METADATA_MAIN_CHARGING:
+ mBluetoothEventTime = eventTime;
+ if (value != null) {
+ mBluetoothMetadataBatteryStatus = Boolean.parseBoolean(
+ new String(value))
+ ? BatteryState.STATUS_CHARGING
+ : BatteryState.STATUS_DISCHARGING;
+ } else {
+ mBluetoothMetadataBatteryStatus = BatteryState.STATUS_UNKNOWN;
+ }
+ break;
+ default:
+ break;
+ }
}
public boolean requiresPolling() {
@@ -677,11 +760,25 @@
// Returns the current battery state that can be used to notify listeners BatteryController.
public State getBatteryStateForReporting() {
- // Give precedence to the Bluetooth battery state if it's present.
- if (mBluetoothState.isPresent) {
- return new State(mBluetoothState);
+ // Give precedence to the Bluetooth battery state, and fall back to the native state.
+ return Objects.requireNonNullElseGet(resolveBluetoothBatteryState(),
+ () -> new State(mState));
+ }
+
+ @Nullable
+ protected State resolveBluetoothBatteryState() {
+ final int level;
+ // Prefer battery level obtained from the metadata over the Bluetooth Hands-Free
+ // Profile (HFP).
+ if (mBluetoothMetadataBatteryLevel >= 0 && mBluetoothMetadataBatteryLevel <= 100) {
+ level = mBluetoothMetadataBatteryLevel;
+ } else if (mBluetoothBatteryLevel >= 0 && mBluetoothBatteryLevel <= 100) {
+ level = mBluetoothBatteryLevel;
+ } else {
+ return null;
}
- return new State(mState);
+ return new State(mState.deviceId, mBluetoothEventTime, true,
+ mBluetoothMetadataBatteryStatus, level / 100.f);
}
@Override
@@ -690,7 +787,7 @@
+ ", Name='" + getInputDeviceName(mState.deviceId) + "'"
+ ", NativeBattery=" + mState
+ ", UEventListener=" + (mUEventBatteryListener != null ? "added" : "none")
- + ", BluetoothBattery=" + mBluetoothState;
+ + ", BluetoothState=" + resolveBluetoothBatteryState();
}
}
@@ -775,12 +872,10 @@
@Override
public State getBatteryStateForReporting() {
- // Give precedence to the Bluetooth battery state if it's present.
- if (mBluetoothState.isPresent) {
- return new State(mBluetoothState);
- }
- return mValidityTimeoutCallback != null
- ? new State(mState) : new State(mState.deviceId);
+ // Give precedence to the Bluetooth battery state, and fall back to the native state.
+ return Objects.requireNonNullElseGet(resolveBluetoothBatteryState(),
+ () -> mValidityTimeoutCallback != null
+ ? new State(mState) : new State(mState.deviceId));
}
@Override
@@ -844,15 +939,24 @@
interface BluetoothBatteryManager {
@VisibleForTesting
interface BluetoothBatteryListener {
- void onBluetoothBatteryChanged(long eventTime, String address);
+ void onBluetoothBatteryChanged(long eventTime, String address, int batteryLevel);
}
- void addListener(BluetoothBatteryListener listener);
- void removeListener(BluetoothBatteryListener listener);
+ // Methods used for obtaining the Bluetooth battery level through Bluetooth HFP.
+ void addBatteryListener(BluetoothBatteryListener listener);
+ void removeBatteryListener(BluetoothBatteryListener listener);
int getBatteryLevel(String address);
+
+ // Methods used for obtaining the battery level through Bluetooth metadata.
+ void addMetadataListener(String address,
+ BluetoothAdapter.OnMetadataChangedListener listener);
+ void removeMetadataListener(String address,
+ BluetoothAdapter.OnMetadataChangedListener listener);
+ byte[] getMetadata(String address, int key);
}
private static class LocalBluetoothBatteryManager implements BluetoothBatteryManager {
private final Context mContext;
+ private final Executor mExecutor;
@Nullable
@GuardedBy("mBroadcastReceiver")
private BluetoothBatteryListener mRegisteredListener;
@@ -868,24 +972,25 @@
if (bluetoothDevice == null) {
return;
}
- // We do not use the EXTRA_LEVEL value. Instead, the battery level will be queried
- // from BluetoothDevice later so that we use a single source for the battery level.
+ final int batteryLevel = intent.getIntExtra(BluetoothDevice.EXTRA_BATTERY_LEVEL,
+ BluetoothDevice.BATTERY_LEVEL_UNKNOWN);
synchronized (mBroadcastReceiver) {
if (mRegisteredListener != null) {
final long eventTime = SystemClock.uptimeMillis();
mRegisteredListener.onBluetoothBatteryChanged(
- eventTime, bluetoothDevice.getAddress());
+ eventTime, bluetoothDevice.getAddress(), batteryLevel);
}
}
}
};
- LocalBluetoothBatteryManager(Context context) {
+ LocalBluetoothBatteryManager(Context context, Looper looper) {
mContext = context;
+ mExecutor = new HandlerExecutor(new Handler(looper));
}
@Override
- public void addListener(BluetoothBatteryListener listener) {
+ public void addBatteryListener(BluetoothBatteryListener listener) {
synchronized (mBroadcastReceiver) {
if (mRegisteredListener != null) {
throw new IllegalStateException(
@@ -898,7 +1003,7 @@
}
@Override
- public void removeListener(BluetoothBatteryListener listener) {
+ public void removeBatteryListener(BluetoothBatteryListener listener) {
synchronized (mBroadcastReceiver) {
if (!listener.equals(mRegisteredListener)) {
throw new IllegalStateException("Listener is not registered.");
@@ -912,6 +1017,28 @@
public int getBatteryLevel(String address) {
return getBluetoothDevice(mContext, address).getBatteryLevel();
}
+
+ @Override
+ public void addMetadataListener(String address,
+ BluetoothAdapter.OnMetadataChangedListener listener) {
+ Objects.requireNonNull(mContext.getSystemService(BluetoothManager.class))
+ .getAdapter().addOnMetadataChangedListener(
+ getBluetoothDevice(mContext, address), mExecutor,
+ listener);
+ }
+
+ @Override
+ public void removeMetadataListener(String address,
+ BluetoothAdapter.OnMetadataChangedListener listener) {
+ Objects.requireNonNull(mContext.getSystemService(BluetoothManager.class))
+ .getAdapter().removeOnMetadataChangedListener(
+ getBluetoothDevice(mContext, address), listener);
+ }
+
+ @Override
+ public byte[] getMetadata(String address, int key) {
+ return getBluetoothDevice(mContext, address).getMetadata(key);
+ }
}
// Helper class that adds copying and printing functionality to IInputDeviceBatteryState.
@@ -954,7 +1081,7 @@
this.capacity = capacity;
}
- private boolean equalsIgnoringUpdateTime(IInputDeviceBatteryState other) {
+ public boolean equalsIgnoringUpdateTime(IInputDeviceBatteryState other) {
long updateTime = this.updateTime;
this.updateTime = other.updateTime;
boolean eq = this.equals(other);
diff --git a/services/core/java/com/android/server/input/InputManagerInternal.java b/services/core/java/com/android/server/input/InputManagerInternal.java
index ca42614..4d03e44 100644
--- a/services/core/java/com/android/server/input/InputManagerInternal.java
+++ b/services/core/java/com/android/server/input/InputManagerInternal.java
@@ -213,4 +213,10 @@
* @param enabled When true, stylus buttons will not be reported through motion events.
*/
public abstract void setStylusButtonMotionEventsEnabled(boolean enabled);
+
+ /**
+ * Notify whether any user activity occurred. This includes any input activity on any
+ * display, external peripherals, fingerprint sensor, etc.
+ */
+ public abstract void notifyUserActivity();
}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index ea7f0bb..be4373a 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -70,6 +70,7 @@
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ShellCallback;
+import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.VibrationEffect;
import android.os.vibrator.StepSegment;
@@ -158,6 +159,11 @@
private static final AdditionalDisplayInputProperties
DEFAULT_ADDITIONAL_DISPLAY_INPUT_PROPERTIES = new AdditionalDisplayInputProperties();
+ // To disable Keyboard backlight control via Framework, run:
+ // 'adb shell setprop persist.input.keyboard_backlight_control.enabled false' (requires restart)
+ private static final boolean KEYBOARD_BACKLIGHT_CONTROL_ENABLED = SystemProperties.getBoolean(
+ "persist.input.keyboard.backlight_control.enabled", true);
+
private final NativeInputManagerService mNative;
private final Context mContext;
@@ -305,7 +311,7 @@
private final BatteryController mBatteryController;
// Manages Keyboard backlight
- private final KeyboardBacklightController mKeyboardBacklightController;
+ private final KeyboardBacklightControllerInterface mKeyboardBacklightController;
// Manages Keyboard modifier keys remapping
private final KeyRemapper mKeyRemapper;
@@ -422,8 +428,10 @@
mKeyboardLayoutManager = new KeyboardLayoutManager(mContext, mNative, mDataStore,
injector.getLooper());
mBatteryController = new BatteryController(mContext, mNative, injector.getLooper());
- mKeyboardBacklightController = new KeyboardBacklightController(mContext, mNative,
- mDataStore, injector.getLooper());
+ mKeyboardBacklightController =
+ KEYBOARD_BACKLIGHT_CONTROL_ENABLED ? new KeyboardBacklightController(mContext,
+ mNative, mDataStore, injector.getLooper())
+ : new KeyboardBacklightControllerInterface() {};
mKeyRemapper = new KeyRemapper(mContext, mNative, mDataStore, injector.getLooper());
mUseDevInputEventForAudioJack =
@@ -3263,6 +3271,7 @@
public void setInteractive(boolean interactive) {
mNative.setInteractive(interactive);
mBatteryController.onInteractiveChanged(interactive);
+ mKeyboardBacklightController.onInteractiveChanged(interactive);
}
@Override
@@ -3346,10 +3355,12 @@
public void onInputMethodSubtypeChangedForKeyboardLayoutMapping(@UserIdInt int userId,
@Nullable InputMethodSubtypeHandle subtypeHandle,
@Nullable InputMethodSubtype subtype) {
- if (DEBUG) {
- Slog.i(TAG, "InputMethodSubtype changed: userId=" + userId
- + " subtypeHandle=" + subtypeHandle);
- }
+ mKeyboardLayoutManager.onInputMethodSubtypeChanged(userId, subtypeHandle, subtype);
+ }
+
+ @Override
+ public void notifyUserActivity() {
+ mKeyboardBacklightController.notifyUserActivity();
}
@Override
@@ -3478,4 +3489,15 @@
applyAdditionalDisplayInputPropertiesLocked(properties);
}
}
+
+ interface KeyboardBacklightControllerInterface {
+ default void incrementKeyboardBacklight(int deviceId) {}
+ default void decrementKeyboardBacklight(int deviceId) {}
+ default void registerKeyboardBacklightListener(IKeyboardBacklightListener l, int pid) {}
+ default void unregisterKeyboardBacklightListener(IKeyboardBacklightListener l, int pid) {}
+ default void onInteractiveChanged(boolean isInteractive) {}
+ default void notifyUserActivity() {}
+ default void systemRunning() {}
+ default void dump(PrintWriter pw) {}
+ }
}
diff --git a/services/core/java/com/android/server/input/KeyboardBacklightController.java b/services/core/java/com/android/server/input/KeyboardBacklightController.java
index 77b0d4f..e1e3dd9 100644
--- a/services/core/java/com/android/server/input/KeyboardBacklightController.java
+++ b/services/core/java/com/android/server/input/KeyboardBacklightController.java
@@ -17,7 +17,6 @@
package com.android.server.input;
import android.annotation.BinderThread;
-import android.annotation.ColorInt;
import android.content.Context;
import android.graphics.Color;
import android.hardware.input.IKeyboardBacklightListener;
@@ -29,6 +28,7 @@
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.util.IndentingPrintWriter;
import android.util.Log;
import android.util.Slog;
@@ -39,15 +39,17 @@
import com.android.internal.annotations.VisibleForTesting;
import java.io.PrintWriter;
+import java.time.Duration;
+import java.util.Arrays;
import java.util.Objects;
import java.util.OptionalInt;
-import java.util.TreeSet;
/**
* A thread-safe component of {@link InputManagerService} responsible for managing the keyboard
* backlight for supported keyboards.
*/
-final class KeyboardBacklightController implements InputManager.InputDeviceListener {
+final class KeyboardBacklightController implements
+ InputManagerService.KeyboardBacklightControllerInterface, InputManager.InputDeviceListener {
private static final String TAG = "KbdBacklightController";
@@ -58,12 +60,20 @@
private enum Direction {
DIRECTION_UP, DIRECTION_DOWN
}
- private static final int MSG_INCREMENT_KEYBOARD_BACKLIGHT = 1;
- private static final int MSG_DECREMENT_KEYBOARD_BACKLIGHT = 2;
+ private static final int MSG_UPDATE_EXISTING_DEVICES = 1;
+ private static final int MSG_INCREMENT_KEYBOARD_BACKLIGHT = 2;
+ private static final int MSG_DECREMENT_KEYBOARD_BACKLIGHT = 3;
+ private static final int MSG_NOTIFY_USER_ACTIVITY = 4;
+ private static final int MSG_NOTIFY_USER_INACTIVITY = 5;
+ private static final int MSG_INTERACTIVE_STATE_CHANGED = 6;
private static final int MAX_BRIGHTNESS = 255;
private static final int NUM_BRIGHTNESS_CHANGE_STEPS = 10;
+
@VisibleForTesting
- static final TreeSet<Integer> BRIGHTNESS_LEVELS = new TreeSet<>();
+ static final long USER_INACTIVITY_THRESHOLD_MILLIS = Duration.ofSeconds(30).toMillis();
+
+ @VisibleForTesting
+ static final int[] BRIGHTNESS_VALUE_FOR_LEVEL = new int[NUM_BRIGHTNESS_CHANGE_STEPS + 1];
private final Context mContext;
private final NativeInputManagerService mNative;
@@ -71,7 +81,12 @@
@GuardedBy("mDataStore")
private final PersistentDataStore mDataStore;
private final Handler mHandler;
- private final SparseArray<Light> mKeyboardBacklights = new SparseArray<>();
+ // Always access on handler thread or need to lock this for synchronization.
+ private final SparseArray<KeyboardBacklightState> mKeyboardBacklights = new SparseArray<>(1);
+ // Maintains state if all backlights should be on or turned off
+ private boolean mIsBacklightOn = false;
+ // Maintains state if currently the device is interactive or not
+ private boolean mIsInteractive = true;
// List of currently registered keyboard backlight listeners
@GuardedBy("mKeyboardBacklightListenerRecords")
@@ -83,8 +98,8 @@
// device brightness range to [0-255]
// Levels are: 0, 25, 51, ..., 255
for (int i = 0; i <= NUM_BRIGHTNESS_CHANGE_STEPS; i++) {
- BRIGHTNESS_LEVELS.add(
- (int) Math.floor(((float) i * MAX_BRIGHTNESS) / NUM_BRIGHTNESS_CHANGE_STEPS));
+ BRIGHTNESS_VALUE_FOR_LEVEL[i] = (int) Math.floor(
+ ((float) i * MAX_BRIGHTNESS) / NUM_BRIGHTNESS_CHANGE_STEPS);
}
}
@@ -96,57 +111,64 @@
mHandler = new Handler(looper, this::handleMessage);
}
- void systemRunning() {
+ @Override
+ public void systemRunning() {
InputManager inputManager = Objects.requireNonNull(
mContext.getSystemService(InputManager.class));
inputManager.registerInputDeviceListener(this, mHandler);
- // Circle through all the already added input devices
- for (int deviceId : inputManager.getInputDeviceIds()) {
- onInputDeviceAdded(deviceId);
- }
+
+ Message msg = Message.obtain(mHandler, MSG_UPDATE_EXISTING_DEVICES,
+ inputManager.getInputDeviceIds());
+ mHandler.sendMessage(msg);
}
+ @Override
public void incrementKeyboardBacklight(int deviceId) {
Message msg = Message.obtain(mHandler, MSG_INCREMENT_KEYBOARD_BACKLIGHT, deviceId);
mHandler.sendMessage(msg);
}
+ @Override
public void decrementKeyboardBacklight(int deviceId) {
Message msg = Message.obtain(mHandler, MSG_DECREMENT_KEYBOARD_BACKLIGHT, deviceId);
mHandler.sendMessage(msg);
}
+ @Override
+ public void notifyUserActivity() {
+ Message msg = Message.obtain(mHandler, MSG_NOTIFY_USER_ACTIVITY);
+ mHandler.sendMessage(msg);
+ }
+
+ @Override
+ public void onInteractiveChanged(boolean isInteractive) {
+ Message msg = Message.obtain(mHandler, MSG_INTERACTIVE_STATE_CHANGED, isInteractive);
+ mHandler.sendMessage(msg);
+ }
+
private void updateKeyboardBacklight(int deviceId, Direction direction) {
InputDevice inputDevice = getInputDevice(deviceId);
- Light keyboardBacklight = mKeyboardBacklights.get(deviceId);
- if (inputDevice == null || keyboardBacklight == null) {
+ KeyboardBacklightState state = mKeyboardBacklights.get(deviceId);
+ if (inputDevice == null || state == null) {
return;
}
+ Light keyboardBacklight = state.mLight;
// Follow preset levels of brightness defined in BRIGHTNESS_LEVELS
- int currBrightness = BRIGHTNESS_LEVELS.floor(Color.alpha(
- mNative.getLightColor(deviceId, keyboardBacklight.getId())));
- int newBrightness;
+ final int currBrightnessLevel = state.mBrightnessLevel;
+ final int newBrightnessLevel;
if (direction == Direction.DIRECTION_UP) {
- newBrightness = currBrightness != MAX_BRIGHTNESS ? BRIGHTNESS_LEVELS.higher(
- currBrightness) : currBrightness;
+ newBrightnessLevel = Math.min(currBrightnessLevel + 1, NUM_BRIGHTNESS_CHANGE_STEPS);
} else {
- newBrightness = currBrightness != 0 ? BRIGHTNESS_LEVELS.lower(currBrightness)
- : currBrightness;
+ newBrightnessLevel = Math.max(currBrightnessLevel - 1, 0);
}
- @ColorInt int newColor = Color.argb(newBrightness, 0, 0, 0);
- mNative.setLightColor(deviceId, keyboardBacklight.getId(), newColor);
- if (DEBUG) {
- Slog.d(TAG, "Changing brightness from " + currBrightness + " to " + newBrightness);
- }
-
- notifyKeyboardBacklightChanged(deviceId, BRIGHTNESS_LEVELS.headSet(newBrightness).size(),
- true/* isTriggeredByKeyPress */);
+ updateBacklightState(deviceId, keyboardBacklight, newBrightnessLevel,
+ true /* isTriggeredByKeyPress */);
synchronized (mDataStore) {
try {
mDataStore.setKeyboardBacklightBrightness(inputDevice.getDescriptor(),
keyboardBacklight.getId(),
- newBrightness);
+ BRIGHTNESS_VALUE_FOR_LEVEL[newBrightnessLevel]);
} finally {
mDataStore.saveIfNeeded();
}
@@ -159,23 +181,83 @@
brightness = mDataStore.getKeyboardBacklightBrightness(
inputDevice.getDescriptor(), keyboardBacklight.getId());
}
- if (!brightness.isEmpty()) {
- mNative.setLightColor(inputDevice.getId(), keyboardBacklight.getId(),
- Color.argb(brightness.getAsInt(), 0, 0, 0));
+ if (brightness.isPresent()) {
+ int brightnessValue = Math.max(0, Math.min(MAX_BRIGHTNESS, brightness.getAsInt()));
+ int brightnessLevel = Arrays.binarySearch(BRIGHTNESS_VALUE_FOR_LEVEL, brightnessValue);
+ updateBacklightState(inputDevice.getId(), keyboardBacklight, brightnessLevel,
+ false /* isTriggeredByKeyPress */);
if (DEBUG) {
Slog.d(TAG, "Restoring brightness level " + brightness.getAsInt());
}
}
}
+ private void handleUserActivity() {
+ // Ignore user activity if device is not interactive. When device becomes interactive, we
+ // will send another user activity to turn backlight on.
+ if (!mIsInteractive) {
+ return;
+ }
+ if (!mIsBacklightOn) {
+ mIsBacklightOn = true;
+ for (int i = 0; i < mKeyboardBacklights.size(); i++) {
+ int deviceId = mKeyboardBacklights.keyAt(i);
+ KeyboardBacklightState state = mKeyboardBacklights.valueAt(i);
+ updateBacklightState(deviceId, state.mLight, state.mBrightnessLevel,
+ false /* isTriggeredByKeyPress */);
+ }
+ }
+ mHandler.removeMessages(MSG_NOTIFY_USER_INACTIVITY);
+ mHandler.sendEmptyMessageAtTime(MSG_NOTIFY_USER_INACTIVITY,
+ SystemClock.uptimeMillis() + USER_INACTIVITY_THRESHOLD_MILLIS);
+ }
+
+ private void handleUserInactivity() {
+ if (mIsBacklightOn) {
+ mIsBacklightOn = false;
+ for (int i = 0; i < mKeyboardBacklights.size(); i++) {
+ int deviceId = mKeyboardBacklights.keyAt(i);
+ KeyboardBacklightState state = mKeyboardBacklights.valueAt(i);
+ updateBacklightState(deviceId, state.mLight, state.mBrightnessLevel,
+ false /* isTriggeredByKeyPress */);
+ }
+ }
+ }
+
+ @VisibleForTesting
+ public void handleInteractiveStateChange(boolean isInteractive) {
+ // Interactive state changes should force the keyboard to turn on/off irrespective of
+ // whether time out occurred or not.
+ mIsInteractive = isInteractive;
+ if (isInteractive) {
+ handleUserActivity();
+ } else {
+ handleUserInactivity();
+ }
+ }
+
private boolean handleMessage(Message msg) {
switch (msg.what) {
+ case MSG_UPDATE_EXISTING_DEVICES:
+ for (int deviceId : (int[]) msg.obj) {
+ onInputDeviceAdded(deviceId);
+ }
+ return true;
case MSG_INCREMENT_KEYBOARD_BACKLIGHT:
updateKeyboardBacklight((int) msg.obj, Direction.DIRECTION_UP);
return true;
case MSG_DECREMENT_KEYBOARD_BACKLIGHT:
updateKeyboardBacklight((int) msg.obj, Direction.DIRECTION_DOWN);
return true;
+ case MSG_NOTIFY_USER_ACTIVITY:
+ handleUserActivity();
+ return true;
+ case MSG_NOTIFY_USER_INACTIVITY:
+ handleUserInactivity();
+ return true;
+ case MSG_INTERACTIVE_STATE_CHANGED:
+ handleInteractiveStateChange((boolean) msg.obj);
+ return true;
}
return false;
}
@@ -204,12 +286,12 @@
mKeyboardBacklights.remove(deviceId);
return;
}
- final Light oldBacklight = mKeyboardBacklights.get(deviceId);
- if (oldBacklight != null && oldBacklight.getId() == keyboardBacklight.getId()) {
+ KeyboardBacklightState state = mKeyboardBacklights.get(deviceId);
+ if (state != null && state.mLight.getId() == keyboardBacklight.getId()) {
return;
}
// The keyboard backlight was added or changed.
- mKeyboardBacklights.put(deviceId, keyboardBacklight);
+ mKeyboardBacklights.put(deviceId, new KeyboardBacklightState(keyboardBacklight));
restoreBacklightBrightness(inputDevice, keyboardBacklight);
}
@@ -232,6 +314,7 @@
/** Register the keyboard backlight listener for a process. */
@BinderThread
+ @Override
public void registerKeyboardBacklightListener(IKeyboardBacklightListener listener,
int pid) {
synchronized (mKeyboardBacklightListenerRecords) {
@@ -252,6 +335,7 @@
/** Unregister the keyboard backlight listener for a process. */
@BinderThread
+ @Override
public void unregisterKeyboardBacklightListener(IKeyboardBacklightListener listener,
int pid) {
synchronized (mKeyboardBacklightListenerRecords) {
@@ -269,13 +353,29 @@
}
}
- private void notifyKeyboardBacklightChanged(int deviceId, int currentBacklightLevel,
+ private void updateBacklightState(int deviceId, Light light, int brightnessLevel,
boolean isTriggeredByKeyPress) {
+ KeyboardBacklightState state = mKeyboardBacklights.get(deviceId);
+ if (state == null) {
+ return;
+ }
+
+ mNative.setLightColor(deviceId, light.getId(),
+ mIsBacklightOn ? Color.argb(BRIGHTNESS_VALUE_FOR_LEVEL[brightnessLevel], 0, 0, 0)
+ : 0);
+ if (DEBUG) {
+ Slog.d(TAG, "Changing state from " + state.mBrightnessLevel + " to " + brightnessLevel
+ + "(isBacklightOn = " + mIsBacklightOn + ")");
+ }
+ state.mBrightnessLevel = brightnessLevel;
+
synchronized (mKeyboardBacklightListenerRecords) {
for (int i = 0; i < mKeyboardBacklightListenerRecords.size(); i++) {
+ IKeyboardBacklightState callbackState = new IKeyboardBacklightState();
+ callbackState.brightnessLevel = brightnessLevel;
+ callbackState.maxBrightnessLevel = NUM_BRIGHTNESS_CHANGE_STEPS;
mKeyboardBacklightListenerRecords.valueAt(i).notifyKeyboardBacklightChanged(
- deviceId, new KeyboardBacklightState(currentBacklightLevel),
- isTriggeredByKeyPress);
+ deviceId, callbackState, isTriggeredByKeyPress);
}
}
}
@@ -286,13 +386,17 @@
}
}
- void dump(PrintWriter pw) {
+ @Override
+ public void dump(PrintWriter pw) {
IndentingPrintWriter ipw = new IndentingPrintWriter(pw);
- ipw.println(TAG + ": " + mKeyboardBacklights.size() + " keyboard backlights");
+ ipw.println(
+ TAG + ": " + mKeyboardBacklights.size() + " keyboard backlights, isBacklightOn = "
+ + mIsBacklightOn);
+
ipw.increaseIndent();
for (int i = 0; i < mKeyboardBacklights.size(); i++) {
- Light light = mKeyboardBacklights.get(i);
- ipw.println(i + ": { id: " + light.getId() + ", name: " + light.getName() + " }");
+ KeyboardBacklightState state = mKeyboardBacklights.valueAt(i);
+ ipw.println(i + ": " + state.toString());
}
ipw.decreaseIndent();
}
@@ -327,17 +431,18 @@
}
}
- private static class KeyboardBacklightState extends IKeyboardBacklightState {
+ private static class KeyboardBacklightState {
+ private final Light mLight;
+ private int mBrightnessLevel;
- KeyboardBacklightState(int brightnessLevel) {
- this.brightnessLevel = brightnessLevel;
- this.maxBrightnessLevel = NUM_BRIGHTNESS_CHANGE_STEPS;
+ KeyboardBacklightState(Light light) {
+ mLight = light;
}
@Override
public String toString() {
- return "KeyboardBacklightState{brightnessLevel=" + brightnessLevel
- + ", maxBrightnessLevel=" + maxBrightnessLevel
+ return "KeyboardBacklightState{Light=" + mLight.getId()
+ + ", BrightnessLevel=" + mBrightnessLevel
+ "}";
}
}
diff --git a/services/core/java/com/android/server/input/KeyboardLayoutManager.java b/services/core/java/com/android/server/input/KeyboardLayoutManager.java
index b8eb901..9e8b9f1 100644
--- a/services/core/java/com/android/server/input/KeyboardLayoutManager.java
+++ b/services/core/java/com/android/server/input/KeyboardLayoutManager.java
@@ -37,6 +37,8 @@
import android.hardware.input.InputDeviceIdentifier;
import android.hardware.input.InputManager;
import android.hardware.input.KeyboardLayout;
+import android.icu.lang.UScript;
+import android.icu.util.ULocale;
import android.os.Bundle;
import android.os.Handler;
import android.os.LocaleList;
@@ -45,6 +47,8 @@
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.FeatureFlagUtils;
import android.util.Log;
import android.util.Slog;
import android.view.InputDevice;
@@ -54,6 +58,7 @@
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.inputmethod.InputMethodSubtypeHandle;
import com.android.internal.messages.nano.SystemMessageProto;
import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.util.XmlUtils;
@@ -63,10 +68,12 @@
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
+import java.util.Map;
import java.util.Objects;
import java.util.stream.Stream;
@@ -94,10 +101,18 @@
@GuardedBy("mDataStore")
private final PersistentDataStore mDataStore;
private final Handler mHandler;
+
private final List<InputDevice> mKeyboardsWithMissingLayouts = new ArrayList<>();
private boolean mKeyboardLayoutNotificationShown = false;
private Toast mSwitchedKeyboardLayoutToast;
+ // This cache stores "best-matched" layouts so that we don't need to run the matching
+ // algorithm repeatedly.
+ @GuardedBy("mKeyboardLayoutCache")
+ private final Map<String, String> mKeyboardLayoutCache = new ArrayMap<>();
+ @Nullable
+ private ImeInfo mCurrentImeInfo;
+
KeyboardLayoutManager(Context context, NativeInputManagerService nativeService,
PersistentDataStore dataStore, Looper looper) {
mContext = context;
@@ -139,8 +154,10 @@
@Override
public void onInputDeviceRemoved(int deviceId) {
- mKeyboardsWithMissingLayouts.removeIf(device -> device.getId() == deviceId);
- maybeUpdateNotification();
+ if (!useNewSettingsUi()) {
+ mKeyboardsWithMissingLayouts.removeIf(device -> device.getId() == deviceId);
+ maybeUpdateNotification();
+ }
}
@Override
@@ -149,18 +166,21 @@
if (inputDevice == null || inputDevice.isVirtual() || !inputDevice.isFullKeyboard()) {
return;
}
- synchronized (mDataStore) {
- String layout = getCurrentKeyboardLayoutForInputDevice(inputDevice.getIdentifier());
- if (layout == null) {
- layout = getDefaultKeyboardLayout(inputDevice);
- if (layout != null) {
- setCurrentKeyboardLayoutForInputDevice(inputDevice.getIdentifier(), layout);
- } else {
- mKeyboardsWithMissingLayouts.add(inputDevice);
+ if (!useNewSettingsUi()) {
+ synchronized (mDataStore) {
+ String layout = getCurrentKeyboardLayoutForInputDevice(inputDevice.getIdentifier());
+ if (layout == null) {
+ layout = getDefaultKeyboardLayout(inputDevice);
+ if (layout != null) {
+ setCurrentKeyboardLayoutForInputDevice(inputDevice.getIdentifier(), layout);
+ } else {
+ mKeyboardsWithMissingLayouts.add(inputDevice);
+ }
}
+ maybeUpdateNotification();
}
- maybeUpdateNotification();
}
+ // TODO(b/259530132): Show notification for new Settings UI
}
private String getDefaultKeyboardLayout(final InputDevice inputDevice) {
@@ -244,6 +264,12 @@
}
}
+ synchronized (mKeyboardLayoutCache) {
+ // Invalidate the cache: With packages being installed/removed, existing cache of
+ // auto-selected layout might not be the best layouts anymore.
+ mKeyboardLayoutCache.clear();
+ }
+
// Reload keyboard layouts.
reloadKeyboardLayouts();
}
@@ -256,6 +282,9 @@
public KeyboardLayout[] getKeyboardLayoutsForInputDevice(
final InputDeviceIdentifier identifier) {
+ if (useNewSettingsUi()) {
+ return new KeyboardLayout[0];
+ }
final String[] enabledLayoutDescriptors =
getEnabledKeyboardLayoutsForInputDevice(identifier);
final ArrayList<KeyboardLayout> enabledLayouts =
@@ -296,6 +325,7 @@
KeyboardLayout[]::new);
}
+ @Nullable
public KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor) {
Objects.requireNonNull(keyboardLayoutDescriptor,
"keyboardLayoutDescriptor must not be null");
@@ -434,21 +464,25 @@
return LocaleList.forLanguageTags(languageTags.replace('|', ','));
}
- /**
- * Builds a layout descriptor for the vendor/product. This returns the
- * descriptor for ids that aren't useful (such as the default 0, 0).
- */
- private String getLayoutDescriptor(InputDeviceIdentifier identifier) {
+ private static String getLayoutDescriptor(@NonNull InputDeviceIdentifier identifier) {
Objects.requireNonNull(identifier, "identifier must not be null");
Objects.requireNonNull(identifier.getDescriptor(), "descriptor must not be null");
if (identifier.getVendorId() == 0 && identifier.getProductId() == 0) {
return identifier.getDescriptor();
}
+ // If vendor id and product id is available, use it as keys. This allows us to have the
+ // same setup for all keyboards with same product and vendor id. i.e. User can swap 2
+ // identical keyboards and still get the same setup.
return "vendor:" + identifier.getVendorId() + ",product:" + identifier.getProductId();
}
+ @Nullable
public String getCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier) {
+ if (useNewSettingsUi()) {
+ Slog.e(TAG, "getCurrentKeyboardLayoutForInputDevice API not supported");
+ return null;
+ }
String key = getLayoutDescriptor(identifier);
synchronized (mDataStore) {
String layout;
@@ -468,9 +502,13 @@
public void setCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
String keyboardLayoutDescriptor) {
+ if (useNewSettingsUi()) {
+ Slog.e(TAG, "setCurrentKeyboardLayoutForInputDevice API not supported");
+ return;
+ }
+
Objects.requireNonNull(keyboardLayoutDescriptor,
"keyboardLayoutDescriptor must not be null");
-
String key = getLayoutDescriptor(identifier);
synchronized (mDataStore) {
try {
@@ -489,6 +527,10 @@
}
public String[] getEnabledKeyboardLayoutsForInputDevice(InputDeviceIdentifier identifier) {
+ if (useNewSettingsUi()) {
+ Slog.e(TAG, "getEnabledKeyboardLayoutsForInputDevice API not supported");
+ return new String[0];
+ }
String key = getLayoutDescriptor(identifier);
synchronized (mDataStore) {
String[] layouts = mDataStore.getKeyboardLayouts(key);
@@ -502,6 +544,10 @@
public void addKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
String keyboardLayoutDescriptor) {
+ if (useNewSettingsUi()) {
+ Slog.e(TAG, "addKeyboardLayoutForInputDevice API not supported");
+ return;
+ }
Objects.requireNonNull(keyboardLayoutDescriptor,
"keyboardLayoutDescriptor must not be null");
@@ -525,6 +571,10 @@
public void removeKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
String keyboardLayoutDescriptor) {
+ if (useNewSettingsUi()) {
+ Slog.e(TAG, "removeKeyboardLayoutForInputDevice API not supported");
+ return;
+ }
Objects.requireNonNull(keyboardLayoutDescriptor,
"keyboardLayoutDescriptor must not be null");
@@ -551,31 +601,11 @@
}
}
- public String getKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
- @UserIdInt int userId, @NonNull InputMethodInfo imeInfo,
- @Nullable InputMethodSubtype imeSubtype) {
- // TODO(b/259530132): Implement the new keyboard layout API: Returning non-IME specific
- // layout for now.
- return getCurrentKeyboardLayoutForInputDevice(identifier);
- }
-
- public void setKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
- @UserIdInt int userId, @NonNull InputMethodInfo imeInfo,
- @Nullable InputMethodSubtype imeSubtype, String keyboardLayoutDescriptor) {
- // TODO(b/259530132): Implement the new keyboard layout API: setting non-IME specific
- // layout for now.
- setCurrentKeyboardLayoutForInputDevice(identifier, keyboardLayoutDescriptor);
- }
-
- public KeyboardLayout[] getKeyboardLayoutListForInputDevice(InputDeviceIdentifier identifier,
- @UserIdInt int userId, @NonNull InputMethodInfo imeInfo,
- @Nullable InputMethodSubtype imeSubtype) {
- // TODO(b/259530132): Implement the new keyboard layout API: Returning list of all
- // layouts for now.
- return getKeyboardLayouts();
- }
-
public void switchKeyboardLayout(int deviceId, int direction) {
+ if (useNewSettingsUi()) {
+ Slog.e(TAG, "switchKeyboardLayout API not supported");
+ return;
+ }
mHandler.obtainMessage(MSG_SWITCH_KEYBOARD_LAYOUT, deviceId, direction).sendToTarget();
}
@@ -616,8 +646,21 @@
}
}
+ @Nullable
public String[] getKeyboardLayoutOverlay(InputDeviceIdentifier identifier) {
- String keyboardLayoutDescriptor = getCurrentKeyboardLayoutForInputDevice(identifier);
+ String keyboardLayoutDescriptor;
+ if (useNewSettingsUi()) {
+ if (mCurrentImeInfo == null) {
+ // Haven't received onInputMethodSubtypeChanged() callback from IMMS. Will reload
+ // keyboard layouts once we receive the callback.
+ return null;
+ }
+
+ keyboardLayoutDescriptor = getKeyboardLayoutForInputDeviceInternal(identifier,
+ mCurrentImeInfo);
+ } else {
+ keyboardLayoutDescriptor = getCurrentKeyboardLayoutForInputDevice(identifier);
+ }
if (keyboardLayoutDescriptor == null) {
return null;
}
@@ -640,6 +683,287 @@
return result;
}
+ @Nullable
+ public String getKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
+ @UserIdInt int userId, @NonNull InputMethodInfo imeInfo,
+ @Nullable InputMethodSubtype imeSubtype) {
+ if (!useNewSettingsUi()) {
+ Slog.e(TAG, "getKeyboardLayoutForInputDevice() API not supported");
+ return null;
+ }
+ InputMethodSubtypeHandle subtypeHandle = InputMethodSubtypeHandle.of(imeInfo, imeSubtype);
+ String layout = getKeyboardLayoutForInputDeviceInternal(identifier,
+ new ImeInfo(userId, subtypeHandle, imeSubtype));
+ if (DEBUG) {
+ Slog.d(TAG, "getKeyboardLayoutForInputDevice() " + identifier.toString() + ", userId : "
+ + userId + ", subtypeHandle = " + subtypeHandle + " -> " + layout);
+ }
+ return layout;
+ }
+
+ public void setKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
+ @UserIdInt int userId, @NonNull InputMethodInfo imeInfo,
+ @Nullable InputMethodSubtype imeSubtype,
+ String keyboardLayoutDescriptor) {
+ if (!useNewSettingsUi()) {
+ Slog.e(TAG, "setKeyboardLayoutForInputDevice() API not supported");
+ return;
+ }
+ Objects.requireNonNull(keyboardLayoutDescriptor,
+ "keyboardLayoutDescriptor must not be null");
+ String key = createLayoutKey(identifier, userId,
+ InputMethodSubtypeHandle.of(imeInfo, imeSubtype));
+ synchronized (mDataStore) {
+ try {
+ // Key for storing into data store = <device descriptor>,<userId>,<subtypeHandle>
+ if (mDataStore.setKeyboardLayout(getLayoutDescriptor(identifier), key,
+ keyboardLayoutDescriptor)) {
+ if (DEBUG) {
+ Slog.d(TAG, "setKeyboardLayoutForInputDevice() " + identifier
+ + " key: " + key
+ + " keyboardLayoutDescriptor: " + keyboardLayoutDescriptor);
+ }
+ mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
+ }
+ } finally {
+ mDataStore.saveIfNeeded();
+ }
+ }
+ }
+
+ public KeyboardLayout[] getKeyboardLayoutListForInputDevice(InputDeviceIdentifier identifier,
+ @UserIdInt int userId, @NonNull InputMethodInfo imeInfo,
+ @Nullable InputMethodSubtype imeSubtype) {
+ if (!useNewSettingsUi()) {
+ Slog.e(TAG, "getKeyboardLayoutListForInputDevice() API not supported");
+ return new KeyboardLayout[0];
+ }
+ return getKeyboardLayoutListForInputDeviceInternal(identifier, new ImeInfo(userId,
+ InputMethodSubtypeHandle.of(imeInfo, imeSubtype), imeSubtype));
+ }
+
+ private KeyboardLayout[] getKeyboardLayoutListForInputDeviceInternal(
+ InputDeviceIdentifier identifier, ImeInfo imeInfo) {
+ String key = createLayoutKey(identifier, imeInfo.mUserId, imeInfo.mImeSubtypeHandle);
+
+ // Fetch user selected layout and always include it in layout list.
+ String userSelectedLayout;
+ synchronized (mDataStore) {
+ userSelectedLayout = mDataStore.getKeyboardLayout(getLayoutDescriptor(identifier), key);
+ }
+
+ final ArrayList<KeyboardLayout> potentialLayouts = new ArrayList<>();
+ String imeLanguageTag;
+ if (imeInfo.mImeSubtype == null) {
+ imeLanguageTag = "";
+ } else {
+ ULocale imeLocale = imeInfo.mImeSubtype.getPhysicalKeyboardHintLanguageTag();
+ imeLanguageTag = imeLocale != null ? imeLocale.toLanguageTag()
+ : imeInfo.mImeSubtype.getCanonicalizedLanguageTag();
+ }
+
+ visitAllKeyboardLayouts(new KeyboardLayoutVisitor() {
+ boolean mDeviceSpecificLayoutAvailable;
+
+ @Override
+ public void visitKeyboardLayout(Resources resources,
+ int keyboardLayoutResId, KeyboardLayout layout) {
+ // Next find any potential layouts that aren't yet enabled for the device. For
+ // devices that have special layouts we assume there's a reason that the generic
+ // layouts don't work for them, so we don't want to return them since it's likely
+ // to result in a poor user experience.
+ if (layout.getVendorId() == identifier.getVendorId()
+ && layout.getProductId() == identifier.getProductId()) {
+ if (!mDeviceSpecificLayoutAvailable) {
+ mDeviceSpecificLayoutAvailable = true;
+ potentialLayouts.clear();
+ }
+ potentialLayouts.add(layout);
+ } else if (layout.getVendorId() == -1 && layout.getProductId() == -1
+ && !mDeviceSpecificLayoutAvailable && isLayoutCompatibleWithLanguageTag(
+ layout, imeLanguageTag)) {
+ potentialLayouts.add(layout);
+ } else if (layout.getDescriptor().equals(userSelectedLayout)) {
+ potentialLayouts.add(layout);
+ }
+ }
+ });
+ // Sort the Keyboard layouts. This is done first by priority then by label. So, system
+ // layouts will come above 3rd party layouts.
+ Collections.sort(potentialLayouts);
+ return potentialLayouts.toArray(new KeyboardLayout[0]);
+ }
+
+ public void onInputMethodSubtypeChanged(@UserIdInt int userId,
+ @Nullable InputMethodSubtypeHandle subtypeHandle,
+ @Nullable InputMethodSubtype subtype) {
+ if (!useNewSettingsUi()) {
+ Slog.e(TAG, "onInputMethodSubtypeChanged() API not supported");
+ return;
+ }
+ if (subtypeHandle == null) {
+ if (DEBUG) {
+ Slog.d(TAG, "No InputMethod is running, ignoring change");
+ }
+ return;
+ }
+ if (mCurrentImeInfo == null || !subtypeHandle.equals(mCurrentImeInfo.mImeSubtypeHandle)
+ || mCurrentImeInfo.mUserId != userId) {
+ mCurrentImeInfo = new ImeInfo(userId, subtypeHandle, subtype);
+ mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
+ if (DEBUG) {
+ Slog.d(TAG, "InputMethodSubtype changed: userId=" + userId
+ + " subtypeHandle=" + subtypeHandle);
+ }
+ }
+ }
+
+ @Nullable
+ private String getKeyboardLayoutForInputDeviceInternal(InputDeviceIdentifier identifier,
+ ImeInfo imeInfo) {
+ InputDevice inputDevice = getInputDevice(identifier);
+ if (inputDevice == null || inputDevice.isVirtual() || !inputDevice.isFullKeyboard()) {
+ return null;
+ }
+ String key = createLayoutKey(identifier, imeInfo.mUserId, imeInfo.mImeSubtypeHandle);
+ String layout;
+ synchronized (mDataStore) {
+ layout = mDataStore.getKeyboardLayout(getLayoutDescriptor(identifier), key);
+ }
+ if (layout == null) {
+ synchronized (mKeyboardLayoutCache) {
+ // Check Auto-selected layout cache to see if layout had been previously selected
+ if (mKeyboardLayoutCache.containsKey(key)) {
+ layout = mKeyboardLayoutCache.get(key);
+ } else {
+ // NOTE: This list is already filtered based on IME Script code
+ KeyboardLayout[] layoutList = getKeyboardLayoutListForInputDeviceInternal(
+ identifier, imeInfo);
+ // Call auto-matching algorithm to find the best matching layout
+ layout = getDefaultKeyboardLayoutBasedOnImeInfo(inputDevice, imeInfo,
+ layoutList);
+ mKeyboardLayoutCache.put(key, layout);
+ }
+ }
+ }
+ return layout;
+ }
+
+ @Nullable
+ private static String getDefaultKeyboardLayoutBasedOnImeInfo(InputDevice inputDevice,
+ ImeInfo imeInfo, KeyboardLayout[] layoutList) {
+ if (imeInfo.mImeSubtypeHandle == null) {
+ return null;
+ }
+
+ Arrays.sort(layoutList);
+
+ // Check <VendorID, ProductID> matching for explicitly declared custom KCM files.
+ for (KeyboardLayout layout : layoutList) {
+ if (layout.getVendorId() == inputDevice.getVendorId()
+ && layout.getProductId() == inputDevice.getProductId()) {
+ if (DEBUG) {
+ Slog.d(TAG,
+ "getDefaultKeyboardLayoutBasedOnImeInfo() : Layout found based on "
+ + "vendor and product Ids. " + inputDevice.getIdentifier()
+ + " : " + layout.getDescriptor());
+ }
+ return layout.getDescriptor();
+ }
+ }
+
+ // Check layout type, language tag information from InputDevice for matching
+ String inputLanguageTag = inputDevice.getKeyboardLanguageTag();
+ if (inputLanguageTag != null) {
+ String layoutDesc = getMatchingLayoutForProvidedLanguageTagAndLayoutType(layoutList,
+ inputLanguageTag, inputDevice.getKeyboardLayoutType());
+
+ if (layoutDesc != null) {
+ if (DEBUG) {
+ Slog.d(TAG,
+ "getDefaultKeyboardLayoutBasedOnImeInfo() : Layout found based on "
+ + "HW information (Language tag and Layout type). "
+ + inputDevice.getIdentifier() + " : " + layoutDesc);
+ }
+ return layoutDesc;
+ }
+ }
+
+ InputMethodSubtype subtype = imeInfo.mImeSubtype;
+ // Can't auto select layout based on IME if subtype or language tag is null
+ if (subtype == null) {
+ return null;
+ }
+
+ // Check layout type, language tag information from IME for matching
+ ULocale pkLocale = subtype.getPhysicalKeyboardHintLanguageTag();
+ String pkLanguageTag =
+ pkLocale != null ? pkLocale.toLanguageTag() : subtype.getCanonicalizedLanguageTag();
+ String layoutDesc = getMatchingLayoutForProvidedLanguageTagAndLayoutType(layoutList,
+ pkLanguageTag, subtype.getPhysicalKeyboardHintLayoutType());
+ if (DEBUG) {
+ Slog.d(TAG,
+ "getDefaultKeyboardLayoutBasedOnImeInfo() : Layout found based on "
+ + "IME locale matching. " + inputDevice.getIdentifier() + " : "
+ + layoutDesc);
+ }
+ return layoutDesc;
+ }
+
+ @Nullable
+ private static String getMatchingLayoutForProvidedLanguageTagAndLayoutType(
+ KeyboardLayout[] layoutList, @NonNull String languageTag, @Nullable String layoutType) {
+ if (layoutType == null || !KeyboardLayout.isLayoutTypeValid(layoutType)) {
+ layoutType = KeyboardLayout.LAYOUT_TYPE_UNDEFINED;
+ }
+ List<KeyboardLayout> layoutsFilteredByLayoutType = new ArrayList<>();
+ for (KeyboardLayout layout : layoutList) {
+ if (layout.getLayoutType().equals(layoutType)) {
+ layoutsFilteredByLayoutType.add(layout);
+ }
+ }
+ String layoutDesc = getMatchingLayoutForProvidedLanguageTag(layoutsFilteredByLayoutType,
+ languageTag);
+ if (layoutDesc != null) {
+ return layoutDesc;
+ }
+
+ return getMatchingLayoutForProvidedLanguageTag(Arrays.asList(layoutList), languageTag);
+ }
+
+ @Nullable
+ private static String getMatchingLayoutForProvidedLanguageTag(List<KeyboardLayout> layoutList,
+ @NonNull String languageTag) {
+ Locale locale = Locale.forLanguageTag(languageTag);
+ String layoutMatchingLanguage = null;
+ String layoutMatchingLanguageAndCountry = null;
+
+ for (KeyboardLayout layout : layoutList) {
+ final LocaleList locales = layout.getLocales();
+ for (int i = 0; i < locales.size(); i++) {
+ final Locale l = locales.get(i);
+ if (l == null) {
+ continue;
+ }
+ if (l.getLanguage().equals(locale.getLanguage())) {
+ if (layoutMatchingLanguage == null) {
+ layoutMatchingLanguage = layout.getDescriptor();
+ }
+ if (l.getCountry().equals(locale.getCountry())) {
+ if (layoutMatchingLanguageAndCountry == null) {
+ layoutMatchingLanguageAndCountry = layout.getDescriptor();
+ }
+ if (l.getVariant().equals(locale.getVariant())) {
+ return layout.getDescriptor();
+ }
+ }
+ }
+ }
+ }
+ return layoutMatchingLanguageAndCountry != null
+ ? layoutMatchingLanguageAndCountry : layoutMatchingLanguage;
+ }
+
private void reloadKeyboardLayouts() {
if (DEBUG) {
Slog.d(TAG, "Reloading keyboard layouts.");
@@ -734,11 +1058,65 @@
}
}
+ private boolean useNewSettingsUi() {
+ return FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_UI);
+ }
+
+ @Nullable
private InputDevice getInputDevice(int deviceId) {
InputManager inputManager = mContext.getSystemService(InputManager.class);
return inputManager != null ? inputManager.getInputDevice(deviceId) : null;
}
+ @Nullable
+ private InputDevice getInputDevice(InputDeviceIdentifier identifier) {
+ InputManager inputManager = mContext.getSystemService(InputManager.class);
+ return inputManager != null ? inputManager.getInputDeviceByDescriptor(
+ identifier.getDescriptor()) : null;
+ }
+
+ private static String createLayoutKey(InputDeviceIdentifier identifier, int userId,
+ @NonNull InputMethodSubtypeHandle subtypeHandle) {
+ Objects.requireNonNull(subtypeHandle, "subtypeHandle must not be null");
+ return "layoutDescriptor:" + getLayoutDescriptor(identifier) + ",userId:" + userId
+ + ",subtypeHandle:" + subtypeHandle.toStringHandle();
+ }
+
+ private static boolean isLayoutCompatibleWithLanguageTag(KeyboardLayout layout,
+ @NonNull String languageTag) {
+ final int[] scriptsFromLanguageTag = UScript.getCode(Locale.forLanguageTag(languageTag));
+ if (scriptsFromLanguageTag.length == 0) {
+ // If no scripts inferred from languageTag then allowing the layout
+ return true;
+ }
+ LocaleList locales = layout.getLocales();
+ if (locales.isEmpty()) {
+ // KCM file doesn't have an associated language tag. This can be from
+ // a 3rd party app so need to include it as a potential layout.
+ return true;
+ }
+ for (int i = 0; i < locales.size(); i++) {
+ final Locale locale = locales.get(i);
+ if (locale == null) {
+ continue;
+ }
+ int[] scripts = UScript.getCode(locale);
+ if (scripts != null && haveCommonValue(scripts, scriptsFromLanguageTag)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static boolean haveCommonValue(int[] arr1, int[] arr2) {
+ for (int a1 : arr1) {
+ for (int a2 : arr2) {
+ if (a1 == a2) return true;
+ }
+ }
+ return false;
+ }
+
private static final class KeyboardLayoutDescriptor {
public String packageName;
public String receiverName;
@@ -767,6 +1145,19 @@
}
}
+ private static class ImeInfo {
+ @UserIdInt int mUserId;
+ @NonNull InputMethodSubtypeHandle mImeSubtypeHandle;
+ @Nullable InputMethodSubtype mImeSubtype;
+
+ ImeInfo(@UserIdInt int userId, @NonNull InputMethodSubtypeHandle imeSubtypeHandle,
+ @Nullable InputMethodSubtype imeSubtype) {
+ mUserId = userId;
+ mImeSubtypeHandle = imeSubtypeHandle;
+ mImeSubtype = imeSubtype;
+ }
+ }
+
private interface KeyboardLayoutVisitor {
void visitKeyboardLayout(Resources resources,
int keyboardLayoutResId, KeyboardLayout layout);
diff --git a/services/core/java/com/android/server/input/PersistentDataStore.java b/services/core/java/com/android/server/input/PersistentDataStore.java
index 375377a7..a2b18362 100644
--- a/services/core/java/com/android/server/input/PersistentDataStore.java
+++ b/services/core/java/com/android/server/input/PersistentDataStore.java
@@ -18,6 +18,7 @@
import android.annotation.Nullable;
import android.hardware.input.TouchCalibration;
+import android.util.ArrayMap;
import android.util.AtomicFile;
import android.util.Slog;
import android.util.SparseIntArray;
@@ -42,6 +43,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.OptionalInt;
@@ -121,6 +123,7 @@
return false;
}
+ @Nullable
public String getCurrentKeyboardLayout(String inputDeviceDescriptor) {
InputDeviceState state = getInputDeviceState(inputDeviceDescriptor);
return state != null ? state.getCurrentKeyboardLayout() : null;
@@ -136,6 +139,22 @@
return false;
}
+ @Nullable
+ public String getKeyboardLayout(String inputDeviceDescriptor, String key) {
+ InputDeviceState state = getInputDeviceState(inputDeviceDescriptor);
+ return state != null ? state.getKeyboardLayout(key) : null;
+ }
+
+ public boolean setKeyboardLayout(String inputDeviceDescriptor, String key,
+ String keyboardLayoutDescriptor) {
+ InputDeviceState state = getOrCreateInputDeviceState(inputDeviceDescriptor);
+ if (state.setKeyboardLayout(key, keyboardLayoutDescriptor)) {
+ setDirty();
+ return true;
+ }
+ return false;
+ }
+
public String[] getKeyboardLayouts(String inputDeviceDescriptor) {
InputDeviceState state = getInputDeviceState(inputDeviceDescriptor);
if (state == null) {
@@ -387,6 +406,8 @@
private final ArrayList<String> mKeyboardLayouts = new ArrayList<String>();
private final SparseIntArray mKeyboardBacklightBrightnessMap = new SparseIntArray();
+ private final Map<String, String> mKeyboardLayoutMap = new ArrayMap<>();
+
public TouchCalibration getTouchCalibration(int surfaceRotation) {
try {
return mTouchCalibration[surfaceRotation];
@@ -410,6 +431,15 @@
}
@Nullable
+ public String getKeyboardLayout(String key) {
+ return mKeyboardLayoutMap.get(key);
+ }
+
+ public boolean setKeyboardLayout(String key, String keyboardLayout) {
+ return !Objects.equals(mKeyboardLayoutMap.put(key, keyboardLayout), keyboardLayout);
+ }
+
+ @Nullable
public String getCurrentKeyboardLayout() {
return mCurrentKeyboardLayout;
}
@@ -507,6 +537,18 @@
changed = true;
}
}
+ List<String> removedEntries = new ArrayList<>();
+ for (String key : mKeyboardLayoutMap.keySet()) {
+ if (!availableKeyboardLayouts.contains(mKeyboardLayoutMap.get(key))) {
+ removedEntries.add(key);
+ }
+ }
+ if (!removedEntries.isEmpty()) {
+ for (String key : removedEntries) {
+ mKeyboardLayoutMap.remove(key);
+ }
+ changed = true;
+ }
return changed;
}
@@ -534,6 +576,18 @@
}
mCurrentKeyboardLayout = descriptor;
}
+ } else if (parser.getName().equals("keyed-keyboard-layout")) {
+ String key = parser.getAttributeValue(null, "key");
+ if (key == null) {
+ throw new XmlPullParserException(
+ "Missing key attribute on keyed-keyboard-layout.");
+ }
+ String layout = parser.getAttributeValue(null, "layout");
+ if (layout == null) {
+ throw new XmlPullParserException(
+ "Missing layout attribute on keyed-keyboard-layout.");
+ }
+ mKeyboardLayoutMap.put(key, layout);
} else if (parser.getName().equals("light-info")) {
int lightId = parser.getAttributeInt(null, "light-id");
int lightBrightness = parser.getAttributeInt(null, "light-brightness");
@@ -607,6 +661,13 @@
serializer.endTag(null, "keyboard-layout");
}
+ for (String key : mKeyboardLayoutMap.keySet()) {
+ serializer.startTag(null, "keyed-keyboard-layout");
+ serializer.attribute(null, "key", key);
+ serializer.attribute(null, "layout", mKeyboardLayoutMap.get(key));
+ serializer.endTag(null, "keyed-keyboard-layout");
+ }
+
for (int i = 0; i < mKeyboardBacklightBrightnessMap.size(); i++) {
serializer.startTag(null, "light-info");
serializer.attributeInt(null, "light-id", mKeyboardBacklightBrightnessMap.keyAt(i));
diff --git a/services/core/java/com/android/server/inputmethod/DefaultImeVisibilityApplier.java b/services/core/java/com/android/server/inputmethod/DefaultImeVisibilityApplier.java
new file mode 100644
index 0000000..35434b7
--- /dev/null
+++ b/services/core/java/com/android/server/inputmethod/DefaultImeVisibilityApplier.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.inputmethod;
+
+import static android.view.inputmethod.ImeTracker.DEBUG_IME_VISIBILITY;
+
+import static com.android.server.EventLogTags.IMF_HIDE_IME;
+import static com.android.server.EventLogTags.IMF_SHOW_IME;
+import static com.android.server.inputmethod.ImeVisibilityStateComputer.STATE_HIDE_IME;
+import static com.android.server.inputmethod.ImeVisibilityStateComputer.STATE_HIDE_IME_EXPLICIT;
+import static com.android.server.inputmethod.ImeVisibilityStateComputer.STATE_HIDE_IME_NOT_ALWAYS;
+import static com.android.server.inputmethod.ImeVisibilityStateComputer.STATE_SHOW_IME;
+import static com.android.server.inputmethod.ImeVisibilityStateComputer.STATE_SHOW_IME_IMPLICIT;
+
+import android.annotation.Nullable;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.ResultReceiver;
+import android.util.EventLog;
+import android.util.Slog;
+import android.view.inputmethod.ImeTracker;
+import android.view.inputmethod.InputMethodManager;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.inputmethod.InputMethodDebug;
+import com.android.internal.inputmethod.SoftInputShowHideReason;
+import com.android.server.LocalServices;
+import com.android.server.wm.WindowManagerInternal;
+
+import java.util.Objects;
+
+/**
+ * The default implementation of {@link ImeVisibilityApplier} used in
+ * {@link InputMethodManagerService}.
+ */
+final class DefaultImeVisibilityApplier implements ImeVisibilityApplier {
+
+ private static final String TAG = "DefaultImeVisibilityApplier";
+
+ private static final boolean DEBUG = InputMethodManagerService.DEBUG;
+
+ private InputMethodManagerService mService;
+
+ private final WindowManagerInternal mWindowManagerInternal;
+
+
+ DefaultImeVisibilityApplier(InputMethodManagerService service) {
+ mService = service;
+ mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
+ }
+
+ @GuardedBy("ImfLock.class")
+ @Override
+ public void performShowIme(IBinder windowToken, @Nullable ImeTracker.Token statsToken,
+ int showFlags, ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
+ final IInputMethodInvoker curMethod = mService.getCurMethodLocked();
+ if (curMethod != null) {
+ // create a placeholder token for IMS so that IMS cannot inject windows into client app.
+ final IBinder showInputToken = new Binder();
+ mService.setRequestImeTokenToWindow(windowToken, showInputToken);
+ if (DEBUG) {
+ Slog.v(TAG, "Calling " + curMethod + ".showSoftInput(" + showInputToken
+ + ", " + showFlags + ", " + resultReceiver + ") for reason: "
+ + InputMethodDebug.softInputDisplayReasonToString(reason));
+ }
+ // TODO(b/192412909): Check if we can always call onShowHideSoftInputRequested() or not.
+ if (curMethod.showSoftInput(showInputToken, statsToken, showFlags, resultReceiver)) {
+ if (DEBUG_IME_VISIBILITY) {
+ EventLog.writeEvent(IMF_SHOW_IME, statsToken.getTag(),
+ Objects.toString(mService.mCurFocusedWindow),
+ InputMethodDebug.softInputDisplayReasonToString(reason),
+ InputMethodDebug.softInputModeToString(
+ mService.mCurFocusedWindowSoftInputMode));
+ }
+ mService.onShowHideSoftInputRequested(true /* show */, windowToken, reason,
+ statsToken);
+ }
+ }
+ }
+
+ @GuardedBy("ImfLock.class")
+ @Override
+ public void performHideIme(IBinder windowToken, @Nullable ImeTracker.Token statsToken,
+ ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
+ final IInputMethodInvoker curMethod = mService.getCurMethodLocked();
+ if (curMethod != null) {
+ final Binder hideInputToken = new Binder();
+ mService.setRequestImeTokenToWindow(windowToken, hideInputToken);
+ // The IME will report its visible state again after the following message finally
+ // delivered to the IME process as an IPC. Hence the inconsistency between
+ // IMMS#mInputShown and IMMS#mImeWindowVis should be resolved spontaneously in
+ // the final state.
+ if (DEBUG) {
+ Slog.v(TAG, "Calling " + curMethod + ".hideSoftInput(0, " + hideInputToken
+ + ", " + resultReceiver + ") for reason: "
+ + InputMethodDebug.softInputDisplayReasonToString(reason));
+ }
+ // TODO(b/192412909): Check if we can always call onShowHideSoftInputRequested() or not.
+ if (curMethod.hideSoftInput(hideInputToken, statsToken, 0, resultReceiver)) {
+ if (DEBUG_IME_VISIBILITY) {
+ EventLog.writeEvent(IMF_HIDE_IME, statsToken.getTag(),
+ Objects.toString(mService.mCurFocusedWindow),
+ InputMethodDebug.softInputDisplayReasonToString(reason),
+ InputMethodDebug.softInputModeToString(
+ mService.mCurFocusedWindowSoftInputMode));
+ }
+ mService.onShowHideSoftInputRequested(false /* show */, windowToken, reason,
+ statsToken);
+ }
+ }
+ }
+
+ @GuardedBy("ImfLock.class")
+ @Override
+ public void applyImeVisibility(IBinder windowToken, @Nullable ImeTracker.Token statsToken,
+ @ImeVisibilityStateComputer.VisibilityState int state) {
+ applyImeVisibility(windowToken, statsToken, state, -1 /* ignore reason */);
+ }
+
+ @GuardedBy("ImfLock.class")
+ void applyImeVisibility(IBinder windowToken, @Nullable ImeTracker.Token statsToken,
+ @ImeVisibilityStateComputer.VisibilityState int state, int reason) {
+ switch (state) {
+ case STATE_SHOW_IME:
+ ImeTracker.forLogging().onProgress(statsToken,
+ ImeTracker.PHASE_SERVER_APPLY_IME_VISIBILITY);
+ // Send to window manager to show IME after IME layout finishes.
+ mWindowManagerInternal.showImePostLayout(windowToken, statsToken);
+ break;
+ case STATE_HIDE_IME:
+ if (mService.mCurFocusedWindowClient != null) {
+ ImeTracker.forLogging().onProgress(statsToken,
+ ImeTracker.PHASE_SERVER_APPLY_IME_VISIBILITY);
+ // IMMS only knows of focused window, not the actual IME target.
+ // e.g. it isn't aware of any window that has both
+ // NOT_FOCUSABLE, ALT_FOCUSABLE_IM flags set and can the IME target.
+ // Send it to window manager to hide IME from IME target window.
+ // TODO(b/139861270): send to mCurClient.client once IMMS is aware of
+ // actual IME target.
+ mWindowManagerInternal.hideIme(windowToken,
+ mService.mCurFocusedWindowClient.mSelfReportedDisplayId, statsToken);
+ } else {
+ ImeTracker.forLogging().onFailed(statsToken,
+ ImeTracker.PHASE_SERVER_APPLY_IME_VISIBILITY);
+ }
+ break;
+ case STATE_HIDE_IME_EXPLICIT:
+ mService.hideCurrentInputLocked(windowToken, statsToken, 0, null, reason);
+ break;
+ case STATE_HIDE_IME_NOT_ALWAYS:
+ mService.hideCurrentInputLocked(windowToken, statsToken,
+ InputMethodManager.HIDE_NOT_ALWAYS, null, reason);
+ break;
+ case STATE_SHOW_IME_IMPLICIT:
+ mService.showCurrentInputLocked(windowToken, statsToken,
+ InputMethodManager.SHOW_IMPLICIT, null, reason);
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid IME visibility state: " + state);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/inputmethod/ImeVisibilityApplier.java b/services/core/java/com/android/server/inputmethod/ImeVisibilityApplier.java
new file mode 100644
index 0000000..e97ec93
--- /dev/null
+++ b/services/core/java/com/android/server/inputmethod/ImeVisibilityApplier.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.inputmethod;
+
+import android.annotation.Nullable;
+import android.os.IBinder;
+import android.os.ResultReceiver;
+import android.view.inputmethod.ImeTracker;
+
+import com.android.internal.inputmethod.SoftInputShowHideReason;
+
+/**
+ * Interface for IME visibility operations like show/hide and update Z-ordering relative to the IME
+ * targeted window.
+ */
+interface ImeVisibilityApplier {
+ /**
+ * Performs showing IME on top of the given window.
+ *
+ * @param windowToken The token of a window that currently has focus.
+ * @param statsToken A token that tracks the progress of an IME request.
+ * @param showFlags Provides additional operating flags to show IME.
+ * @param resultReceiver If non-null, this will be called back to the caller when
+ * it has processed request to tell what it has done.
+ * @param reason The reason for requesting to show IME.
+ */
+ default void performShowIme(IBinder windowToken, @Nullable ImeTracker.Token statsToken,
+ int showFlags, ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {}
+
+ /**
+ * Performs hiding IME to the given window
+ *
+ * @param windowToken The token of a window that currently has focus.
+ * @param statsToken A token that tracks the progress of an IME request.
+ * @param resultReceiver If non-null, this will be called back to the caller when
+ * it has processed request to tell what it has done.
+ * @param reason The reason for requesting to hide IME.
+ */
+ default void performHideIme(IBinder windowToken, @Nullable ImeTracker.Token statsToken,
+ ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {}
+
+ /**
+ * Applies the IME visibility from {@link android.inputmethodservice.InputMethodService} with
+ * according to the given visibility state.
+ *
+ * @param windowToken The token of a window for applying the IME visibility
+ * @param statsToken A token that tracks the progress of an IME request.
+ * @param state The new IME visibility state for the applier to handle
+ */
+ default void applyImeVisibility(IBinder windowToken, @Nullable ImeTracker.Token statsToken,
+ @ImeVisibilityStateComputer.VisibilityState int state) {}
+
+ /**
+ * Updates the IME Z-ordering relative to the given window.
+ *
+ * This used to adjust the IME relative layer of the window during
+ * {@link InputMethodManagerService} is in switching IME clients.
+ *
+ * @param windowToken The token of a window to update the Z-ordering relative to the IME.
+ */
+ default void updateImeLayeringByTarget(IBinder windowToken) {
+ // TODO: add a method in WindowManagerInternal to call DC#updateImeInputAndControlTarget
+ // here to end up updating IME layering after IMMS#attachNewInputLocked called.
+ }
+}
diff --git a/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java b/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java
new file mode 100644
index 0000000..10c16b6
--- /dev/null
+++ b/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java
@@ -0,0 +1,680 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.inputmethod;
+
+import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HIDDEN;
+import static android.server.inputmethod.InputMethodManagerServiceProto.ACCESSIBILITY_REQUESTING_NO_SOFT_KEYBOARD;
+import static android.server.inputmethod.InputMethodManagerServiceProto.INPUT_SHOWN;
+import static android.server.inputmethod.InputMethodManagerServiceProto.SHOW_EXPLICITLY_REQUESTED;
+import static android.server.inputmethod.InputMethodManagerServiceProto.SHOW_FORCED;
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.Display.INVALID_DISPLAY;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_STATE;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED;
+import static android.view.WindowManager.LayoutParams.SoftInputModeFlags;
+
+import static com.android.internal.inputmethod.InputMethodDebug.softInputModeToString;
+import static com.android.server.inputmethod.InputMethodManagerService.computeImeDisplayIdForTarget;
+
+import android.accessibilityservice.AccessibilityService;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.content.res.Configuration;
+import android.os.IBinder;
+import android.util.PrintWriterPrinter;
+import android.util.Printer;
+import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
+import android.view.WindowManager;
+import android.view.inputmethod.ImeTracker;
+import android.view.inputmethod.InputMethod;
+import android.view.inputmethod.InputMethodManager;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.inputmethod.SoftInputShowHideReason;
+import com.android.server.LocalServices;
+import com.android.server.wm.WindowManagerInternal;
+
+import java.io.PrintWriter;
+import java.util.WeakHashMap;
+
+/**
+ * A computer used by {@link InputMethodManagerService} that computes the IME visibility state
+ * according the given {@link ImeTargetWindowState} from the focused window or the app requested IME
+ * visibility from {@link InputMethodManager}.
+ */
+public final class ImeVisibilityStateComputer {
+
+ private static final String TAG = "ImeVisibilityStateComputer";
+
+ private static final boolean DEBUG = InputMethodManagerService.DEBUG;
+
+ private final InputMethodManagerService mService;
+ private final WindowManagerInternal mWindowManagerInternal;
+
+ final InputMethodManagerService.ImeDisplayValidator mImeDisplayValidator;
+
+ /**
+ * A map used to track the requested IME target window and its state. The key represents the
+ * token of the window and the value is the corresponding IME window state.
+ */
+ private final WeakHashMap<IBinder, ImeTargetWindowState> mRequestWindowStateMap =
+ new WeakHashMap<>();
+
+ /**
+ * Set if IME was explicitly told to show the input method.
+ *
+ * @see InputMethodManager#SHOW_IMPLICIT that we set the value is {@code false}.
+ * @see InputMethodManager#HIDE_IMPLICIT_ONLY that system will not hide IME when the value is
+ * {@code true}.
+ */
+ boolean mRequestedShowExplicitly;
+
+ /**
+ * Set if we were forced to be shown.
+ *
+ * @see InputMethodManager#SHOW_FORCED
+ * @see InputMethodManager#HIDE_NOT_ALWAYS
+ */
+ boolean mShowForced;
+
+ /**
+ * Set if we last told the input method to show itself.
+ */
+ private boolean mInputShown;
+
+ /** Represent the invalid IME visibility state */
+ public static final int STATE_INVALID = -1;
+
+ /** State to handle hiding the IME window requested by the app. */
+ public static final int STATE_HIDE_IME = 0;
+
+ /** State to handle showing the IME window requested by the app. */
+ public static final int STATE_SHOW_IME = 1;
+
+ /** State to handle showing the IME window with making the overlay window above it. */
+ public static final int STATE_SHOW_IME_ABOVE_OVERLAY = 2;
+
+ /** State to handle showing the IME window with making the overlay window behind it. */
+ public static final int STATE_SHOW_IME_BEHIND_OVERLAY = 3;
+
+ /** State to handle showing an IME preview surface during the app was loosing the IME focus */
+ public static final int STATE_SHOW_IME_SNAPSHOT = 4;
+
+ public static final int STATE_HIDE_IME_EXPLICIT = 5;
+
+ public static final int STATE_HIDE_IME_NOT_ALWAYS = 6;
+
+ public static final int STATE_SHOW_IME_IMPLICIT = 7;
+ @IntDef({
+ STATE_INVALID,
+ STATE_HIDE_IME,
+ STATE_SHOW_IME,
+ STATE_SHOW_IME_ABOVE_OVERLAY,
+ STATE_SHOW_IME_BEHIND_OVERLAY,
+ STATE_SHOW_IME_SNAPSHOT,
+ STATE_HIDE_IME_EXPLICIT,
+ STATE_HIDE_IME_NOT_ALWAYS,
+ STATE_SHOW_IME_IMPLICIT,
+ })
+ @interface VisibilityState {}
+
+ /**
+ * The policy to configure the IME visibility.
+ */
+ private final ImeVisibilityPolicy mPolicy;
+
+ public ImeVisibilityStateComputer(@NonNull InputMethodManagerService service) {
+ this(service,
+ LocalServices.getService(WindowManagerInternal.class),
+ LocalServices.getService(WindowManagerInternal.class)::getDisplayImePolicy,
+ new ImeVisibilityPolicy());
+ }
+
+ @VisibleForTesting
+ public ImeVisibilityStateComputer(@NonNull InputMethodManagerService service,
+ @NonNull Injector injector) {
+ this(service, injector.getWmService(), injector.getImeValidator(),
+ new ImeVisibilityPolicy());
+ }
+
+ interface Injector {
+ default WindowManagerInternal getWmService() {
+ return null;
+ }
+
+ default InputMethodManagerService.ImeDisplayValidator getImeValidator() {
+ return null;
+ }
+ }
+
+ private ImeVisibilityStateComputer(InputMethodManagerService service,
+ WindowManagerInternal wmService,
+ InputMethodManagerService.ImeDisplayValidator imeDisplayValidator,
+ ImeVisibilityPolicy imePolicy) {
+ mService = service;
+ mWindowManagerInternal = wmService;
+ mImeDisplayValidator = imeDisplayValidator;
+ mPolicy = imePolicy;
+ }
+
+ /**
+ * Called when {@link InputMethodManagerService} is processing the show IME request.
+ * @param statsToken The token for tracking this show request
+ * @param showFlags The additional operation flags to indicate whether this show request mode is
+ * implicit or explicit.
+ * @return {@code true} when the computer has proceed this show request operation.
+ */
+ boolean onImeShowFlags(@NonNull ImeTracker.Token statsToken, int showFlags) {
+ if (mPolicy.mA11yRequestingNoSoftKeyboard || mPolicy.mImeHiddenByDisplayPolicy) {
+ ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_SERVER_ACCESSIBILITY);
+ return false;
+ }
+ ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_SERVER_ACCESSIBILITY);
+ if ((showFlags & InputMethodManager.SHOW_FORCED) != 0) {
+ mRequestedShowExplicitly = true;
+ mShowForced = true;
+ } else if ((showFlags & InputMethodManager.SHOW_IMPLICIT) == 0) {
+ mRequestedShowExplicitly = true;
+ }
+ return true;
+ }
+
+ /**
+ * Called when {@link InputMethodManagerService} is processing the hide IME request.
+ * @param statsToken The token for tracking this hide request
+ * @param hideFlags The additional operation flags to indicate whether this hide request mode is
+ * implicit or explicit.
+ * @return {@code true} when the computer has proceed this hide request operations.
+ */
+ boolean canHideIme(@NonNull ImeTracker.Token statsToken, int hideFlags) {
+ if ((hideFlags & InputMethodManager.HIDE_IMPLICIT_ONLY) != 0
+ && (mRequestedShowExplicitly || mShowForced)) {
+ if (DEBUG) Slog.v(TAG, "Not hiding: explicit show not cancelled by non-explicit hide");
+ ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_SERVER_HIDE_IMPLICIT);
+ return false;
+ }
+ if (mShowForced && (hideFlags & InputMethodManager.HIDE_NOT_ALWAYS) != 0) {
+ if (DEBUG) Slog.v(TAG, "Not hiding: forced show not cancelled by not-always hide");
+ ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_SERVER_HIDE_NOT_ALWAYS);
+ return false;
+ }
+ ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_SERVER_HIDE_NOT_ALWAYS);
+ return true;
+ }
+
+ int getImeShowFlags() {
+ int flags = 0;
+ if (mShowForced) {
+ flags |= InputMethod.SHOW_FORCED | InputMethod.SHOW_EXPLICIT;
+ } else if (mRequestedShowExplicitly) {
+ flags |= InputMethod.SHOW_EXPLICIT;
+ } else {
+ flags |= InputMethodManager.SHOW_IMPLICIT;
+ }
+ return flags;
+ }
+
+ void clearImeShowFlags() {
+ mRequestedShowExplicitly = false;
+ mShowForced = false;
+ mInputShown = false;
+ }
+
+ int computeImeDisplayId(@NonNull ImeTargetWindowState state, int displayId) {
+ final int displayToShowIme = computeImeDisplayIdForTarget(displayId, mImeDisplayValidator);
+ state.setImeDisplayId(displayToShowIme);
+ final boolean imeHiddenByPolicy = displayToShowIme == INVALID_DISPLAY;
+ mPolicy.setImeHiddenByDisplayPolicy(imeHiddenByPolicy);
+ return displayToShowIme;
+ }
+
+ /**
+ * Request to show/hide IME from the given window.
+ *
+ * @param windowToken The window which requests to show/hide IME.
+ * @param showIme {@code true} means to show IME, {@code false} otherwise.
+ * Note that in the computer will take this option to compute the
+ * visibility state, it could be {@link #STATE_SHOW_IME} or
+ * {@link #STATE_HIDE_IME}.
+ */
+ void requestImeVisibility(IBinder windowToken, boolean showIme) {
+ ImeTargetWindowState state = getOrCreateWindowState(windowToken);
+ if (!mPolicy.mPendingA11yRequestingHideKeyboard) {
+ state.setRequestedImeVisible(showIme);
+ } else {
+ // As A11y requests no IME is just a temporary, so we don't change the requested IME
+ // visible in case the last visibility state goes wrong after leaving from the a11y
+ // policy.
+ mPolicy.mPendingA11yRequestingHideKeyboard = false;
+ }
+ setWindowStateInner(windowToken, state);
+ }
+
+ ImeTargetWindowState getOrCreateWindowState(IBinder windowToken) {
+ ImeTargetWindowState state = mRequestWindowStateMap.get(windowToken);
+ if (state == null) {
+ state = new ImeTargetWindowState(SOFT_INPUT_STATE_UNSPECIFIED, 0, false, false, false);
+ }
+ return state;
+ }
+
+ ImeTargetWindowState getWindowStateOrNull(IBinder windowToken) {
+ ImeTargetWindowState state = mRequestWindowStateMap.get(windowToken);
+ return state;
+ }
+
+ void setRequestImeTokenToWindow(IBinder windowToken, IBinder token) {
+ ImeTargetWindowState state = getWindowStateOrNull(windowToken);
+ if (state != null) {
+ state.setRequestImeToken(token);
+ setWindowStateInner(windowToken, state);
+ }
+ }
+
+ void setWindowState(IBinder windowToken, @NonNull ImeTargetWindowState newState) {
+ final ImeTargetWindowState state = mRequestWindowStateMap.get(windowToken);
+ if (state != null && newState.hasEdiorFocused()) {
+ // Inherit the last requested IME visible state when the target window is still
+ // focused with an editor.
+ newState.setRequestedImeVisible(state.mRequestedImeVisible);
+ }
+ setWindowStateInner(windowToken, newState);
+ }
+
+ private void setWindowStateInner(IBinder windowToken, @NonNull ImeTargetWindowState newState) {
+ if (DEBUG) Slog.d(TAG, "setWindowStateInner, windowToken=" + windowToken
+ + ", state=" + newState);
+ mRequestWindowStateMap.put(windowToken, newState);
+ }
+
+ static class ImeVisibilityResult {
+ private final @VisibilityState int mState;
+ private final @SoftInputShowHideReason int mReason;
+
+ ImeVisibilityResult(@VisibilityState int state, @SoftInputShowHideReason int reason) {
+ mState = state;
+ mReason = reason;
+ }
+
+ @VisibilityState int getState() {
+ return mState;
+ }
+
+ @SoftInputShowHideReason int getReason() {
+ return mReason;
+ }
+ }
+
+ ImeVisibilityResult computeState(ImeTargetWindowState state, boolean allowVisible) {
+ // TODO: Output the request IME visibility state according to the requested window state
+ final int softInputVisibility = state.mSoftInputModeState & SOFT_INPUT_MASK_STATE;
+ // Should we auto-show the IME even if the caller has not
+ // specified what should be done with it?
+ // We only do this automatically if the window can resize
+ // to accommodate the IME (so what the user sees will give
+ // them good context without input information being obscured
+ // by the IME) or if running on a large screen where there
+ // is more room for the target window + IME.
+ final boolean doAutoShow =
+ (state.mSoftInputModeState & WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST)
+ == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
+ || mService.mRes.getConfiguration().isLayoutSizeAtLeast(
+ Configuration.SCREENLAYOUT_SIZE_LARGE);
+ final boolean isForwardNavigation = (state.mSoftInputModeState
+ & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0;
+
+ // We shows the IME when the system allows the IME focused target window to restore the
+ // IME visibility (e.g. switching to the app task when last time the IME is visible).
+ // Note that we don't restore IME visibility for some cases (e.g. when the soft input
+ // state is ALWAYS_HIDDEN or STATE_HIDDEN with forward navigation).
+ // Because the app might leverage these flags to hide soft-keyboard with showing their own
+ // UI for input.
+ if (state.hasEdiorFocused() && shouldRestoreImeVisibility(state)) {
+ if (DEBUG) Slog.v(TAG, "Will show input to restore visibility");
+ // Inherit the last requested IME visible state when the target window is still
+ // focused with an editor.
+ state.setRequestedImeVisible(true);
+ setWindowStateInner(getWindowTokenFrom(state), state);
+ return new ImeVisibilityResult(STATE_SHOW_IME_IMPLICIT,
+ SoftInputShowHideReason.SHOW_RESTORE_IME_VISIBILITY);
+ }
+
+ switch (softInputVisibility) {
+ case WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED:
+ if (state.hasImeFocusChanged() && (!state.hasEdiorFocused() || !doAutoShow)) {
+ if (WindowManager.LayoutParams.mayUseInputMethod(state.getWindowFlags())) {
+ // There is no focus view, and this window will
+ // be behind any soft input window, so hide the
+ // soft input window if it is shown.
+ if (DEBUG) Slog.v(TAG, "Unspecified window will hide input");
+ return new ImeVisibilityResult(STATE_HIDE_IME_NOT_ALWAYS,
+ SoftInputShowHideReason.HIDE_UNSPECIFIED_WINDOW);
+ }
+ } else if (state.hasEdiorFocused() && doAutoShow && isForwardNavigation) {
+ // There is a focus view, and we are navigating forward
+ // into the window, so show the input window for the user.
+ // We only do this automatically if the window can resize
+ // to accommodate the IME (so what the user sees will give
+ // them good context without input information being obscured
+ // by the IME) or if running on a large screen where there
+ // is more room for the target window + IME.
+ if (DEBUG) Slog.v(TAG, "Unspecified window will show input");
+ return new ImeVisibilityResult(STATE_SHOW_IME_IMPLICIT,
+ SoftInputShowHideReason.SHOW_AUTO_EDITOR_FORWARD_NAV);
+ }
+ break;
+ case WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED:
+ // Do nothing but preserving the last IME requested visibility state.
+ final ImeTargetWindowState lastState =
+ getWindowStateOrNull(mService.mLastImeTargetWindow);
+ if (lastState != null) {
+ state.setRequestedImeVisible(lastState.mRequestedImeVisible);
+ }
+ break;
+ case WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN:
+ if (isForwardNavigation) {
+ if (DEBUG) Slog.v(TAG, "Window asks to hide input going forward");
+ return new ImeVisibilityResult(STATE_HIDE_IME_EXPLICIT,
+ SoftInputShowHideReason.HIDE_STATE_HIDDEN_FORWARD_NAV);
+ }
+ break;
+ case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN:
+ if (state.hasImeFocusChanged()) {
+ if (DEBUG) Slog.v(TAG, "Window asks to hide input");
+ return new ImeVisibilityResult(STATE_HIDE_IME_EXPLICIT,
+ SoftInputShowHideReason.HIDE_ALWAYS_HIDDEN_STATE);
+ }
+ break;
+ case WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE:
+ if (isForwardNavigation) {
+ if (allowVisible) {
+ if (DEBUG) Slog.v(TAG, "Window asks to show input going forward");
+ return new ImeVisibilityResult(STATE_SHOW_IME_IMPLICIT,
+ SoftInputShowHideReason.SHOW_STATE_VISIBLE_FORWARD_NAV);
+ } else {
+ Slog.e(TAG, "SOFT_INPUT_STATE_VISIBLE is ignored because"
+ + " there is no focused view that also returns true from"
+ + " View#onCheckIsTextEditor()");
+ }
+ }
+ break;
+ case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE:
+ if (DEBUG) Slog.v(TAG, "Window asks to always show input");
+ if (allowVisible) {
+ if (state.hasImeFocusChanged()) {
+ return new ImeVisibilityResult(STATE_SHOW_IME_IMPLICIT,
+ SoftInputShowHideReason.SHOW_STATE_ALWAYS_VISIBLE);
+ }
+ } else {
+ Slog.e(TAG, "SOFT_INPUT_STATE_ALWAYS_VISIBLE is ignored because"
+ + " there is no focused view that also returns true from"
+ + " View#onCheckIsTextEditor()");
+ }
+ break;
+ }
+
+ if (!state.hasImeFocusChanged()) {
+ // On previous platforms, when Dialogs re-gained focus, the Activity behind
+ // would briefly gain focus first, and dismiss the IME.
+ // On R that behavior has been fixed, but unfortunately apps have come
+ // to rely on this behavior to hide the IME when the editor no longer has focus
+ // To maintain compatibility, we are now hiding the IME when we don't have
+ // an editor upon refocusing a window.
+ if (state.isStartInputByGainFocus()) {
+ if (DEBUG) Slog.v(TAG, "Same window without editor will hide input");
+ return new ImeVisibilityResult(STATE_HIDE_IME_EXPLICIT,
+ SoftInputShowHideReason.HIDE_SAME_WINDOW_FOCUSED_WITHOUT_EDITOR);
+ }
+ }
+ if (!state.hasEdiorFocused() && mInputShown && state.isStartInputByGainFocus()
+ && mService.mInputMethodDeviceConfigs.shouldHideImeWhenNoEditorFocus()) {
+ // Hide the soft-keyboard when the system do nothing for softInputModeState
+ // of the window being gained focus without an editor. This behavior benefits
+ // to resolve some unexpected IME visible cases while that window with following
+ // configurations being switched from an IME shown window:
+ // 1) SOFT_INPUT_STATE_UNCHANGED state without an editor
+ // 2) SOFT_INPUT_STATE_VISIBLE state without an editor
+ // 3) SOFT_INPUT_STATE_ALWAYS_VISIBLE state without an editor
+ if (DEBUG) Slog.v(TAG, "Window without editor will hide input");
+ return new ImeVisibilityResult(STATE_HIDE_IME_EXPLICIT,
+ SoftInputShowHideReason.HIDE_WINDOW_GAINED_FOCUS_WITHOUT_EDITOR);
+ }
+ return null;
+ }
+
+ IBinder getWindowTokenFrom(IBinder requestImeToken) {
+ for (IBinder windowToken : mRequestWindowStateMap.keySet()) {
+ final ImeTargetWindowState state = mRequestWindowStateMap.get(windowToken);
+ if (state.getRequestImeToken() == requestImeToken) {
+ return windowToken;
+ }
+ }
+ // Fallback to the focused window for some edge cases (e.g. relaunching the activity)
+ return mService.mCurFocusedWindow;
+ }
+
+ IBinder getWindowTokenFrom(ImeTargetWindowState windowState) {
+ for (IBinder windowToken : mRequestWindowStateMap.keySet()) {
+ final ImeTargetWindowState state = mRequestWindowStateMap.get(windowToken);
+ if (state == windowState) {
+ return windowToken;
+ }
+ }
+ return null;
+ }
+
+ boolean shouldRestoreImeVisibility(@NonNull ImeTargetWindowState state) {
+ final int softInputMode = state.getSoftInputModeState();
+ switch (softInputMode & WindowManager.LayoutParams.SOFT_INPUT_MASK_STATE) {
+ case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN:
+ return false;
+ case WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN:
+ if ((softInputMode & SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
+ return false;
+ }
+ }
+ return mWindowManagerInternal.shouldRestoreImeVisibility(getWindowTokenFrom(state));
+ }
+
+ boolean isInputShown() {
+ return mInputShown;
+ }
+
+ void setInputShown(boolean inputShown) {
+ mInputShown = inputShown;
+ }
+
+ void dumpDebug(ProtoOutputStream proto, long fieldId) {
+ proto.write(SHOW_EXPLICITLY_REQUESTED, mRequestedShowExplicitly);
+ proto.write(SHOW_FORCED, mShowForced);
+ proto.write(ACCESSIBILITY_REQUESTING_NO_SOFT_KEYBOARD,
+ mPolicy.isA11yRequestNoSoftKeyboard());
+ proto.write(INPUT_SHOWN, mInputShown);
+ }
+
+ void dump(PrintWriter pw) {
+ final Printer p = new PrintWriterPrinter(pw);
+ p.println(" mRequestedShowExplicitly=" + mRequestedShowExplicitly
+ + " mShowForced=" + mShowForced);
+ p.println(" mImeHiddenByDisplayPolicy=" + mPolicy.isImeHiddenByDisplayPolicy());
+ p.println(" mInputShown=" + mInputShown);
+ }
+
+ /**
+ * A settings class to manage all IME related visibility policies or settings.
+ *
+ * This is used for the visibility computer to manage and tell
+ * {@link InputMethodManagerService} if the requested IME visibility is valid from
+ * application call or the focus window.
+ */
+ static class ImeVisibilityPolicy {
+ /**
+ * {@code true} if the Ime policy has been set to
+ * {@link WindowManager#DISPLAY_IME_POLICY_HIDE}.
+ *
+ * This prevents the IME from showing when it otherwise may have shown.
+ */
+ private boolean mImeHiddenByDisplayPolicy;
+
+ /**
+ * Set when the accessibility service requests to hide IME by
+ * {@link AccessibilityService.SoftKeyboardController#setShowMode}
+ */
+ private boolean mA11yRequestingNoSoftKeyboard;
+
+ /**
+ * Used when A11y request to hide IME temporary when receiving
+ * {@link AccessibilityService#SHOW_MODE_HIDDEN} from
+ * {@link android.provider.Settings.Secure#ACCESSIBILITY_SOFT_KEYBOARD_MODE} without
+ * changing the requested IME visible state.
+ */
+ private boolean mPendingA11yRequestingHideKeyboard;
+
+ void setImeHiddenByDisplayPolicy(boolean hideIme) {
+ mImeHiddenByDisplayPolicy = hideIme;
+ }
+
+ boolean isImeHiddenByDisplayPolicy() {
+ return mImeHiddenByDisplayPolicy;
+ }
+
+ void setA11yRequestNoSoftKeyboard(int keyboardShowMode) {
+ mA11yRequestingNoSoftKeyboard =
+ (keyboardShowMode & AccessibilityService.SHOW_MODE_MASK) == SHOW_MODE_HIDDEN;
+ if (mA11yRequestingNoSoftKeyboard) {
+ mPendingA11yRequestingHideKeyboard = true;
+ }
+ }
+
+ boolean isA11yRequestNoSoftKeyboard() {
+ return mA11yRequestingNoSoftKeyboard;
+ }
+ }
+
+ ImeVisibilityPolicy getImePolicy() {
+ return mPolicy;
+ }
+
+ /**
+ * A class that represents the current state of the IME target window.
+ */
+ static class ImeTargetWindowState {
+ ImeTargetWindowState(@SoftInputModeFlags int softInputModeState, int windowFlags,
+ boolean imeFocusChanged, boolean hasFocusedEditor,
+ boolean isStartInputByGainFocus) {
+ mSoftInputModeState = softInputModeState;
+ mWindowFlags = windowFlags;
+ mImeFocusChanged = imeFocusChanged;
+ mHasFocusedEditor = hasFocusedEditor;
+ mIsStartInputByGainFocus = isStartInputByGainFocus;
+ }
+
+ /**
+ * Visibility state for this window. By default no state has been specified.
+ */
+ private final @SoftInputModeFlags int mSoftInputModeState;
+
+ private final int mWindowFlags;
+
+ /**
+ * {@code true} means the IME focus changed from the previous window, {@code false}
+ * otherwise.
+ */
+ private final boolean mImeFocusChanged;
+
+ /**
+ * {@code true} when the window has focused an editor, {@code false} otherwise.
+ */
+ private final boolean mHasFocusedEditor;
+
+ private final boolean mIsStartInputByGainFocus;
+
+ /**
+ * Set if the client has asked for the input method to be shown.
+ */
+ private boolean mRequestedImeVisible;
+
+ /**
+ * A identifier for knowing the requester of {@link InputMethodManager#showSoftInput} or
+ * {@link InputMethodManager#hideSoftInputFromWindow}.
+ */
+ private IBinder mRequestImeToken;
+
+ /**
+ * The IME target display id for which the latest startInput was called.
+ */
+ private int mImeDisplayId = DEFAULT_DISPLAY;
+
+ boolean hasImeFocusChanged() {
+ return mImeFocusChanged;
+ }
+
+ boolean hasEdiorFocused() {
+ return mHasFocusedEditor;
+ }
+
+ boolean isStartInputByGainFocus() {
+ return mIsStartInputByGainFocus;
+ }
+
+ int getSoftInputModeState() {
+ return mSoftInputModeState;
+ }
+
+ int getWindowFlags() {
+ return mWindowFlags;
+ }
+
+ private void setImeDisplayId(int imeDisplayId) {
+ mImeDisplayId = imeDisplayId;
+ }
+
+ int getImeDisplayId() {
+ return mImeDisplayId;
+ }
+
+ private void setRequestedImeVisible(boolean requestedImeVisible) {
+ mRequestedImeVisible = requestedImeVisible;
+ }
+
+ boolean isRequestedImeVisible() {
+ return mRequestedImeVisible;
+ }
+
+ void setRequestImeToken(IBinder token) {
+ mRequestImeToken = token;
+ }
+
+ IBinder getRequestImeToken() {
+ return mRequestImeToken;
+ }
+
+ @Override
+ public String toString() {
+ return "ImeTargetWindowState{ imeToken " + mRequestImeToken
+ + " imeFocusChanged " + mImeFocusChanged
+ + " hasEditorFocused " + mHasFocusedEditor
+ + " requestedImeVisible " + mRequestedImeVisible
+ + " imeDisplayId " + mImeDisplayId
+ + " softInputModeState " + softInputModeToString(mSoftInputModeState)
+ + " isStartInputByGainFocus " + mIsStartInputByGainFocus
+ + "}";
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java b/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java
index 079234c..ba9e280 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java
@@ -350,7 +350,7 @@
// should now try to restart the service for us.
mLastBindTime = SystemClock.uptimeMillis();
clearCurMethodAndSessions();
- mService.clearInputShowRequestLocked();
+ mService.clearInputShownLocked();
mService.unbindCurrentClientLocked(UnbindReason.DISCONNECT_IME);
}
}
@@ -469,11 +469,11 @@
@GuardedBy("ImfLock.class")
private boolean bindCurrentInputMethodService(ServiceConnection conn, int flags) {
- if (getCurIntent() == null || conn == null) {
+ if (mCurIntent == null || conn == null) {
Slog.e(TAG, "--- bind failed: service = " + mCurIntent + ", conn = " + conn);
return false;
}
- return mContext.bindServiceAsUser(getCurIntent(), conn, flags,
+ return mContext.bindServiceAsUser(mCurIntent, conn, flags,
new UserHandle(mSettings.getCurrentUserId()));
}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 5b9a663..0a20d93 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -20,7 +20,6 @@
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL;
import static android.os.IServiceManager.DUMP_FLAG_PROTO;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
-import static android.server.inputmethod.InputMethodManagerServiceProto.ACCESSIBILITY_REQUESTING_NO_SOFT_KEYBOARD;
import static android.server.inputmethod.InputMethodManagerServiceProto.BACK_DISPOSITION;
import static android.server.inputmethod.InputMethodManagerServiceProto.BOUND_TO_METHOD;
import static android.server.inputmethod.InputMethodManagerServiceProto.CUR_ATTRIBUTE;
@@ -34,31 +33,25 @@
import static android.server.inputmethod.InputMethodManagerServiceProto.CUR_TOKEN_DISPLAY_ID;
import static android.server.inputmethod.InputMethodManagerServiceProto.HAVE_CONNECTION;
import static android.server.inputmethod.InputMethodManagerServiceProto.IME_WINDOW_VISIBILITY;
-import static android.server.inputmethod.InputMethodManagerServiceProto.INPUT_SHOWN;
import static android.server.inputmethod.InputMethodManagerServiceProto.IN_FULLSCREEN_MODE;
import static android.server.inputmethod.InputMethodManagerServiceProto.IS_INTERACTIVE;
import static android.server.inputmethod.InputMethodManagerServiceProto.LAST_IME_TARGET_WINDOW_NAME;
import static android.server.inputmethod.InputMethodManagerServiceProto.LAST_SWITCH_USER_ID;
-import static android.server.inputmethod.InputMethodManagerServiceProto.SHOW_EXPLICITLY_REQUESTED;
-import static android.server.inputmethod.InputMethodManagerServiceProto.SHOW_FORCED;
import static android.server.inputmethod.InputMethodManagerServiceProto.SHOW_IME_WITH_HARD_KEYBOARD;
-import static android.server.inputmethod.InputMethodManagerServiceProto.SHOW_REQUESTED;
import static android.server.inputmethod.InputMethodManagerServiceProto.SYSTEM_READY;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.WindowManager.DISPLAY_IME_POLICY_HIDE;
import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL;
-import static android.view.inputmethod.ImeTracker.DEBUG_IME_VISIBILITY;
-import static com.android.server.EventLogTags.IMF_HIDE_IME;
-import static com.android.server.EventLogTags.IMF_SHOW_IME;
+import static com.android.server.inputmethod.ImeVisibilityStateComputer.ImeTargetWindowState;
+import static com.android.server.inputmethod.ImeVisibilityStateComputer.ImeVisibilityResult;
import static com.android.server.inputmethod.InputMethodBindingController.TIME_TO_RECONNECT;
import static com.android.server.inputmethod.InputMethodUtils.isSoftInputModeStateVisibleAllowed;
import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.Manifest;
-import android.accessibilityservice.AccessibilityService;
import android.annotation.AnyThread;
import android.annotation.BinderThread;
import android.annotation.DrawableRes;
@@ -83,7 +76,6 @@
import android.content.pm.PackageManagerInternal;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
-import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.graphics.Matrix;
@@ -126,7 +118,6 @@
import android.view.InputChannel;
import android.view.InputDevice;
import android.view.MotionEvent;
-import android.view.View;
import android.view.WindowManager;
import android.view.WindowManager.DisplayImePolicy;
import android.view.WindowManager.LayoutParams;
@@ -299,6 +290,12 @@
@NonNull private final InputMethodBindingController mBindingController;
@NonNull private final AutofillSuggestionsController mAutofillController;
+ @GuardedBy("ImfLock.class")
+ @NonNull private final ImeVisibilityStateComputer mVisibilityStateComputer;
+
+ @GuardedBy("ImfLock.class")
+ @NonNull private final DefaultImeVisibilityApplier mVisibilityApplier;
+
/**
* Cache the result of {@code LocalServices.getService(AudioManagerInternal.class)}.
*
@@ -530,13 +527,6 @@
}
/**
- * {@code true} if the Ime policy has been set to {@link WindowManager#DISPLAY_IME_POLICY_HIDE}.
- *
- * This prevents the IME from showing when it otherwise may have shown.
- */
- boolean mImeHiddenByDisplayPolicy;
-
- /**
* The client that is currently bound to an input method.
*/
private ClientState mCurClient;
@@ -632,26 +622,6 @@
return mBindingController.hasConnection();
}
- /**
- * Set if the client has asked for the input method to be shown.
- */
- private boolean mShowRequested;
-
- /**
- * Set if we were explicitly told to show the input method.
- */
- boolean mShowExplicitlyRequested;
-
- /**
- * Set if we were forced to be shown.
- */
- boolean mShowForced;
-
- /**
- * Set if we last told the input method to show itself.
- */
- private boolean mInputShown;
-
/** The token tracking the current IME request or {@code null} otherwise. */
@Nullable
private ImeTracker.Token mCurStatsToken;
@@ -707,9 +677,7 @@
* The display ID of the input method indicates the fallback display which returned by
* {@link #computeImeDisplayIdForTarget}.
*/
- private static final int FALLBACK_DISPLAY_ID = DEFAULT_DISPLAY;
-
- final ImeDisplayValidator mImeDisplayValidator;
+ static final int FALLBACK_DISPLAY_ID = DEFAULT_DISPLAY;
/**
* If non-null, this is the input method service we are currently connected
@@ -786,7 +754,6 @@
int mImeWindowVis;
private LocaleList mLastSystemLocales;
- private boolean mAccessibilityRequestingNoSoftKeyboard;
private final MyPackageMonitor mMyPackageMonitor = new MyPackageMonitor();
private final String mSlotIme;
@@ -974,22 +941,6 @@
}
/**
- * Map of generated token to windowToken that is requesting
- * {@link InputMethodManager#showSoftInput(View, int)}.
- * This map tracks origin of showSoftInput requests.
- */
- @GuardedBy("ImfLock.class")
- private final WeakHashMap<IBinder, IBinder> mShowRequestWindowMap = new WeakHashMap<>();
-
- /**
- * Map of generated token to windowToken that is requesting
- * {@link InputMethodManager#hideSoftInputFromWindow(IBinder, int)}.
- * This map tracks origin of hideSoftInput requests.
- */
- @GuardedBy("ImfLock.class")
- private final WeakHashMap<IBinder, IBinder> mHideRequestWindowMap = new WeakHashMap<>();
-
- /**
* A ring buffer to store the history of {@link StartInputInfo}.
*/
private static final class StartInputHistory {
@@ -1207,17 +1158,14 @@
} else if (accessibilityRequestingNoImeUri.equals(uri)) {
final int accessibilitySoftKeyboardSetting = Settings.Secure.getIntForUser(
mContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 0 /* def */, mUserId);
- mAccessibilityRequestingNoSoftKeyboard =
- (accessibilitySoftKeyboardSetting & AccessibilityService.SHOW_MODE_MASK)
- == AccessibilityService.SHOW_MODE_HIDDEN;
- if (mAccessibilityRequestingNoSoftKeyboard) {
- final boolean showRequested = mShowRequested;
+ Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 0, mUserId);
+ mVisibilityStateComputer.getImePolicy().setA11yRequestNoSoftKeyboard(
+ accessibilitySoftKeyboardSetting);
+ if (mVisibilityStateComputer.getImePolicy().isA11yRequestNoSoftKeyboard()) {
hideCurrentInputLocked(mCurFocusedWindow, null /* statsToken */,
0 /* flags */, null /* resultReceiver */,
SoftInputShowHideReason.HIDE_SETTINGS_ON_CHANGE);
- mShowRequested = showRequested;
- } else if (mShowRequested) {
+ } else if (isShowRequestedForCurrentWindow()) {
showCurrentInputImplicitLocked(mCurFocusedWindow,
SoftInputShowHideReason.SHOW_SETTINGS_ON_CHANGE);
}
@@ -1722,7 +1670,6 @@
mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
mImePlatformCompatUtils = new ImePlatformCompatUtils();
mInputMethodDeviceConfigs = new InputMethodDeviceConfigs();
- mImeDisplayValidator = mWindowManagerInternal::getDisplayImePolicy;
mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
@@ -1747,6 +1694,10 @@
? bindingControllerForTesting
: new InputMethodBindingController(this);
mAutofillController = new AutofillSuggestionsController(this);
+
+ mVisibilityStateComputer = new ImeVisibilityStateComputer(this);
+ mVisibilityApplier = new DefaultImeVisibilityApplier(this);
+
mPreventImeStartupUnlessTextEditor = mRes.getBoolean(
com.android.internal.R.bool.config_preventImeStartupUnlessTextEditor);
mNonPreemptibleInputMethods = mRes.getStringArray(
@@ -2007,6 +1958,19 @@
}
@BinderThread
+ @Nullable
+ @Override
+ public InputMethodInfo getCurrentInputMethodInfoAsUser(@UserIdInt int userId) {
+ if (UserHandle.getCallingUserId() != userId) {
+ mContext.enforceCallingPermission(
+ Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
+ }
+ synchronized (ImfLock.class) {
+ return queryDefaultInputMethodForUserIdLocked(userId);
+ }
+ }
+
+ @BinderThread
@NonNull
@Override
public List<InputMethodInfo> getInputMethodList(@UserIdInt int userId,
@@ -2326,7 +2290,7 @@
mCurClient.mSessionRequestedForAccessibility = false;
mCurClient = null;
mCurVirtualDisplayToScreenMatrix = null;
- ImeTracker.get().onFailed(mCurStatsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
+ ImeTracker.forLogging().onFailed(mCurStatsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
mCurStatsToken = null;
mMenuController.hideInputMethodMenuLocked();
@@ -2334,32 +2298,20 @@
}
@GuardedBy("ImfLock.class")
- void clearInputShowRequestLocked() {
- mShowRequested = mInputShown;
- mInputShown = false;
+ void clearInputShownLocked() {
+ mVisibilityStateComputer.setInputShown(false);
}
@GuardedBy("ImfLock.class")
- private int getImeShowFlagsLocked() {
- int flags = 0;
- if (mShowForced) {
- flags |= InputMethod.SHOW_FORCED
- | InputMethod.SHOW_EXPLICIT;
- } else if (mShowExplicitlyRequested) {
- flags |= InputMethod.SHOW_EXPLICIT;
- }
- return flags;
+ private boolean isInputShown() {
+ return mVisibilityStateComputer.isInputShown();
}
@GuardedBy("ImfLock.class")
- private int getAppShowFlagsLocked() {
- int flags = 0;
- if (mShowForced) {
- flags |= InputMethodManager.SHOW_FORCED;
- } else if (!mShowExplicitlyRequested) {
- flags |= InputMethodManager.SHOW_IMPLICIT;
- }
- return flags;
+ private boolean isShowRequestedForCurrentWindow() {
+ final ImeTargetWindowState state = mVisibilityStateComputer.getWindowStateOrNull(
+ mCurFocusedWindow);
+ return state != null && state.isRequestedImeVisible();
}
@GuardedBy("ImfLock.class")
@@ -2398,12 +2350,13 @@
setEnabledSessionLocked(session);
session.mMethod.startInput(startInputToken, mCurInputConnection, mCurEditorInfo, restarting,
navButtonFlags, mCurImeDispatcher);
- if (mShowRequested) {
+ if (isShowRequestedForCurrentWindow()) {
if (DEBUG) Slog.v(TAG, "Attach new input asks to show input");
// Re-use current statsToken, if it exists.
final ImeTracker.Token statsToken = mCurStatsToken;
mCurStatsToken = null;
- showCurrentInputLocked(mCurFocusedWindow, statsToken, getAppShowFlagsLocked(),
+ showCurrentInputLocked(mCurFocusedWindow, statsToken,
+ mVisibilityStateComputer.getImeShowFlags(),
null /* resultReceiver */, SoftInputShowHideReason.ATTACH_NEW_INPUT);
}
@@ -2518,17 +2471,20 @@
// Compute the final shown display ID with validated cs.selfReportedDisplayId for this
// session & other conditions.
- mDisplayIdToShowIme = computeImeDisplayIdForTarget(cs.mSelfReportedDisplayId,
- mImeDisplayValidator);
+ ImeTargetWindowState winState = mVisibilityStateComputer.getWindowStateOrNull(
+ mCurFocusedWindow);
+ if (winState == null) {
+ return InputBindResult.NOT_IME_TARGET_WINDOW;
+ }
+ final int csDisplayId = cs.mSelfReportedDisplayId;
+ mDisplayIdToShowIme = mVisibilityStateComputer.computeImeDisplayId(winState, csDisplayId);
- if (mDisplayIdToShowIme == INVALID_DISPLAY) {
- mImeHiddenByDisplayPolicy = true;
+ if (mVisibilityStateComputer.getImePolicy().isImeHiddenByDisplayPolicy()) {
hideCurrentInputLocked(mCurFocusedWindow, null /* statsToken */, 0 /* flags */,
null /* resultReceiver */,
SoftInputShowHideReason.HIDE_DISPLAY_IME_POLICY_HIDE);
return InputBindResult.NO_IME;
}
- mImeHiddenByDisplayPolicy = false;
if (mCurClient != cs) {
prepareClientSwitchLocked(cs);
@@ -2613,7 +2569,7 @@
if (!mPreventImeStartupUnlessTextEditor) {
return false;
}
- if (mShowRequested) {
+ if (isShowRequestedForCurrentWindow()) {
return false;
}
if (isSoftInputModeStateVisibleAllowed(unverifiedTargetSdkVersion, startInputFlags)) {
@@ -3320,7 +3276,8 @@
"InputMethodManagerService#showSoftInput");
synchronized (ImfLock.class) {
if (!canInteractWithImeLocked(uid, client, "showSoftInput", statsToken)) {
- ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_SERVER_CLIENT_FOCUSED);
+ ImeTracker.forLogging().onFailed(
+ statsToken, ImeTracker.PHASE_SERVER_CLIENT_FOCUSED);
return false;
}
final long ident = Binder.clearCallingIdentity();
@@ -3385,6 +3342,11 @@
}
}
+ @GuardedBy("ImfLock.class")
+ void setRequestImeTokenToWindow(IBinder windowToken, IBinder token) {
+ mVisibilityStateComputer.setRequestImeTokenToWindow(windowToken, token);
+ }
+
@BinderThread
@Override
public void reportPerceptibleAsync(IBinder windowToken, boolean perceptible) {
@@ -3415,64 +3377,39 @@
// TODO(b/261565259): to avoid using null, add package name in ClientState
final String packageName = (mCurEditorInfo != null) ? mCurEditorInfo.packageName : null;
final int uid = mCurClient != null ? mCurClient.mUid : -1;
- statsToken = ImeTracker.get().onRequestShow(packageName, uid,
+ statsToken = ImeTracker.forLogging().onRequestShow(packageName, uid,
ImeTracker.ORIGIN_SERVER_START_INPUT, reason);
}
- mShowRequested = true;
- if (mAccessibilityRequestingNoSoftKeyboard || mImeHiddenByDisplayPolicy) {
- ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_SERVER_ACCESSIBILITY);
+ if (!mVisibilityStateComputer.onImeShowFlags(statsToken, flags)) {
return false;
}
- ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_ACCESSIBILITY);
-
- if ((flags & InputMethodManager.SHOW_FORCED) != 0) {
- mShowExplicitlyRequested = true;
- mShowForced = true;
- } else if ((flags & InputMethodManager.SHOW_IMPLICIT) == 0) {
- mShowExplicitlyRequested = true;
- }
if (!mSystemReady) {
- ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_SERVER_SYSTEM_READY);
+ ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_SERVER_SYSTEM_READY);
return false;
}
- ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_SYSTEM_READY);
+ ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_SERVER_SYSTEM_READY);
+ mVisibilityStateComputer.requestImeVisibility(windowToken, true);
+
+ // Ensure binding the connection when IME is going to show.
mBindingController.setCurrentMethodVisible();
final IInputMethodInvoker curMethod = getCurMethodLocked();
+ ImeTracker.forLogging().onCancelled(mCurStatsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
if (curMethod != null) {
- // create a placeholder token for IMS so that IMS cannot inject windows into client app.
- Binder showInputToken = new Binder();
- mShowRequestWindowMap.put(showInputToken, windowToken);
- ImeTracker.get().onCancelled(mCurStatsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
- ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_HAS_IME);
+ ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_SERVER_HAS_IME);
mCurStatsToken = null;
- final int showFlags = getImeShowFlagsLocked();
- if (DEBUG) {
- Slog.v(TAG, "Calling " + curMethod + ".showSoftInput(" + showInputToken
- + ", " + showFlags + ", " + resultReceiver + ") for reason: "
- + InputMethodDebug.softInputDisplayReasonToString(reason));
- }
if (lastClickToolType != MotionEvent.TOOL_TYPE_UNKNOWN) {
curMethod.updateEditorToolType(lastClickToolType);
}
- // TODO(b/192412909): Check if we can always call onShowHideSoftInputRequested() or not.
- if (curMethod.showSoftInput(showInputToken, statsToken, showFlags, resultReceiver)) {
- if (DEBUG_IME_VISIBILITY) {
- EventLog.writeEvent(IMF_SHOW_IME, statsToken.getTag(),
- Objects.toString(mCurFocusedWindow),
- InputMethodDebug.softInputDisplayReasonToString(reason),
- InputMethodDebug.softInputModeToString(mCurFocusedWindowSoftInputMode));
- }
- onShowHideSoftInputRequested(true /* show */, windowToken, reason, statsToken);
- }
- mInputShown = true;
+ mVisibilityApplier.performShowIme(windowToken, statsToken,
+ mVisibilityStateComputer.getImeShowFlags(), resultReceiver, reason);
+ mVisibilityStateComputer.setInputShown(true);
return true;
} else {
- ImeTracker.get().onCancelled(mCurStatsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
- ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
+ ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
mCurStatsToken = statsToken;
}
return false;
@@ -3487,10 +3424,11 @@
"InputMethodManagerService#hideSoftInput");
synchronized (ImfLock.class) {
if (!canInteractWithImeLocked(uid, client, "hideSoftInput", statsToken)) {
- if (mInputShown) {
- ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_SERVER_CLIENT_FOCUSED);
+ if (isInputShown()) {
+ ImeTracker.forLogging().onFailed(
+ statsToken, ImeTracker.PHASE_SERVER_CLIENT_FOCUSED);
} else {
- ImeTracker.get().onCancelled(statsToken,
+ ImeTracker.forLogging().onCancelled(statsToken,
ImeTracker.PHASE_SERVER_CLIENT_FOCUSED);
}
return false;
@@ -3523,24 +3461,13 @@
} else {
uid = -1;
}
- statsToken = ImeTracker.get().onRequestHide(packageName, uid,
+ statsToken = ImeTracker.forLogging().onRequestHide(packageName, uid,
ImeTracker.ORIGIN_SERVER_HIDE_INPUT, reason);
}
- if ((flags & InputMethodManager.HIDE_IMPLICIT_ONLY) != 0
- && (mShowExplicitlyRequested || mShowForced)) {
- if (DEBUG) Slog.v(TAG, "Not hiding: explicit show not cancelled by non-explicit hide");
- ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_SERVER_HIDE_IMPLICIT);
+ if (!mVisibilityStateComputer.canHideIme(statsToken, flags)) {
return false;
}
- ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_HIDE_IMPLICIT);
-
- if (mShowForced && (flags & InputMethodManager.HIDE_NOT_ALWAYS) != 0) {
- if (DEBUG) Slog.v(TAG, "Not hiding: forced show not cancelled by not-always hide");
- ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_SERVER_HIDE_NOT_ALWAYS);
- return false;
- }
- ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_HIDE_NOT_ALWAYS);
// There is a chance that IMM#hideSoftInput() is called in a transient state where
// IMMS#InputShown is already updated to be true whereas IMMS#mImeWindowVis is still waiting
@@ -3549,49 +3476,28 @@
// application process as a valid request, and have even promised such a behavior with CTS
// since Android Eclair. That's why we need to accept IMM#hideSoftInput() even when only
// IMMS#InputShown indicates that the software keyboard is shown.
- // TODO: Clean up, IMMS#mInputShown, IMMS#mImeWindowVis and mShowRequested.
+ // TODO(b/246309664): Clean up IMMS#mImeWindowVis
IInputMethodInvoker curMethod = getCurMethodLocked();
- final boolean shouldHideSoftInput = (curMethod != null)
- && (mInputShown || (mImeWindowVis & InputMethodService.IME_ACTIVE) != 0);
- boolean res;
+ final boolean shouldHideSoftInput = curMethod != null
+ && (isInputShown() || (mImeWindowVis & InputMethodService.IME_ACTIVE) != 0);
+
+ mVisibilityStateComputer.requestImeVisibility(windowToken, false);
if (shouldHideSoftInput) {
- final Binder hideInputToken = new Binder();
- mHideRequestWindowMap.put(hideInputToken, windowToken);
// The IME will report its visible state again after the following message finally
// delivered to the IME process as an IPC. Hence the inconsistency between
// IMMS#mInputShown and IMMS#mImeWindowVis should be resolved spontaneously in
// the final state.
- ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_SHOULD_HIDE);
- if (DEBUG) {
- Slog.v(TAG, "Calling " + curMethod + ".hideSoftInput(0, " + hideInputToken
- + ", " + resultReceiver + ") for reason: "
- + InputMethodDebug.softInputDisplayReasonToString(reason));
- }
- // TODO(b/192412909): Check if we can always call onShowHideSoftInputRequested() or not.
- if (curMethod.hideSoftInput(hideInputToken, statsToken, 0 /* flags */,
- resultReceiver)) {
- if (DEBUG_IME_VISIBILITY) {
- EventLog.writeEvent(IMF_HIDE_IME, statsToken.getTag(),
- Objects.toString(mCurFocusedWindow),
- InputMethodDebug.softInputDisplayReasonToString(reason),
- InputMethodDebug.softInputModeToString(mCurFocusedWindowSoftInputMode));
- }
- onShowHideSoftInputRequested(false /* show */, windowToken, reason, statsToken);
- }
- res = true;
+ ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_SERVER_SHOULD_HIDE);
+ mVisibilityApplier.performHideIme(windowToken, statsToken, resultReceiver, reason);
} else {
- ImeTracker.get().onCancelled(statsToken, ImeTracker.PHASE_SERVER_SHOULD_HIDE);
- res = false;
+ ImeTracker.forLogging().onCancelled(statsToken, ImeTracker.PHASE_SERVER_SHOULD_HIDE);
}
mBindingController.setCurrentMethodNotVisible();
- mInputShown = false;
- mShowRequested = false;
- mShowExplicitlyRequested = false;
- mShowForced = false;
+ mVisibilityStateComputer.clearImeShowFlags();
// Cancel existing statsToken for show IME as we got a hide request.
- ImeTracker.get().onCancelled(mCurStatsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
+ ImeTracker.forLogging().onCancelled(mCurStatsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
mCurStatsToken = null;
- return res;
+ return shouldHideSoftInput;
}
private boolean isImeClientFocused(IBinder windowToken, ClientState cs) {
@@ -3738,8 +3644,9 @@
// In case mShowForced flag affects the next client to keep IME visible, when the current
// client is leaving due to the next focused client, we clear mShowForced flag when the
// next client's targetSdkVersion is T or higher.
- if (mCurFocusedWindow != windowToken && mShowForced && shouldClearFlag) {
- mShowForced = false;
+ final boolean showForced = mVisibilityStateComputer.mShowForced;
+ if (mCurFocusedWindow != windowToken && showForced && shouldClearFlag) {
+ mVisibilityStateComputer.mShowForced = false;
}
// cross-profile access is always allowed here to allow profile-switching.
@@ -3763,6 +3670,12 @@
final boolean startInputByWinGainedFocus =
(startInputFlags & StartInputFlags.WINDOW_GAINED_FOCUS) != 0;
+ // Init the focused window state (e.g. whether the editor has focused or IME focus has
+ // changed from another window).
+ final ImeTargetWindowState windowState = new ImeTargetWindowState(softInputMode,
+ windowFlags, !sameWindowFocused, isTextEditor, startInputByWinGainedFocus);
+ mVisibilityStateComputer.setWindowState(windowToken, windowState);
+
if (sameWindowFocused && isTextEditor) {
if (DEBUG) {
Slog.w(TAG, "Window already focused, ignoring focus gain of: " + client
@@ -3785,74 +3698,21 @@
mCurFocusedWindowClient = cs;
mCurPerceptible = true;
- // Should we auto-show the IME even if the caller has not
- // specified what should be done with it?
- // We only do this automatically if the window can resize
- // to accommodate the IME (so what the user sees will give
- // them good context without input information being obscured
- // by the IME) or if running on a large screen where there
- // is more room for the target window + IME.
- final boolean doAutoShow =
- (softInputMode & LayoutParams.SOFT_INPUT_MASK_ADJUST)
- == LayoutParams.SOFT_INPUT_ADJUST_RESIZE
- || mRes.getConfiguration().isLayoutSizeAtLeast(
- Configuration.SCREENLAYOUT_SIZE_LARGE);
-
// We want to start input before showing the IME, but after closing
// it. We want to do this after closing it to help the IME disappear
// more quickly (not get stuck behind it initializing itself for the
// new focused input, even if its window wants to hide the IME).
boolean didStart = false;
-
InputBindResult res = null;
- // We show the IME when the system allows the IME focused target window to restore the
- // IME visibility (e.g. switching to the app task when last time the IME is visible).
- // Note that we don't restore IME visibility for some cases (e.g. when the soft input
- // state is ALWAYS_HIDDEN or STATE_HIDDEN with forward navigation).
- // Because the app might leverage these flags to hide soft-keyboard with showing their own
- // UI for input.
- if (isTextEditor && editorInfo != null
- && shouldRestoreImeVisibility(windowToken, softInputMode)) {
- if (DEBUG) Slog.v(TAG, "Will show input to restore visibility");
- res = startInputUncheckedLocked(cs, inputContext, remoteAccessibilityInputConnection,
- editorInfo, startInputFlags, startInputReason, unverifiedTargetSdkVersion,
- imeDispatcher);
- showCurrentInputImplicitLocked(windowToken,
- SoftInputShowHideReason.SHOW_RESTORE_IME_VISIBILITY);
- return res;
- }
- switch (softInputMode & LayoutParams.SOFT_INPUT_MASK_STATE) {
- case LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED:
- if (!sameWindowFocused && (!isTextEditor || !doAutoShow)) {
- if (LayoutParams.mayUseInputMethod(windowFlags)) {
- // There is no focus view, and this window will
- // be behind any soft input window, so hide the
- // soft input window if it is shown.
- if (DEBUG) Slog.v(TAG, "Unspecified window will hide input");
- hideCurrentInputLocked(mCurFocusedWindow, null /* statsToken */,
- InputMethodManager.HIDE_NOT_ALWAYS, null /* resultReceiver */,
- SoftInputShowHideReason.HIDE_UNSPECIFIED_WINDOW);
-
- // If focused display changed, we should unbind current method
- // to make app window in previous display relayout after Ime
- // window token removed.
- // Note that we can trust client's display ID as long as it matches
- // to the display ID obtained from the window.
- if (cs.mSelfReportedDisplayId != mCurTokenDisplayId) {
- mBindingController.unbindCurrentMethod();
- }
- }
- } else if (isTextEditor && doAutoShow
- && (softInputMode & LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
- // There is a focus view, and we are navigating forward
- // into the window, so show the input window for the user.
- // We only do this automatically if the window can resize
- // to accommodate the IME (so what the user sees will give
- // them good context without input information being obscured
- // by the IME) or if running on a large screen where there
- // is more room for the target window + IME.
- if (DEBUG) Slog.v(TAG, "Unspecified window will show input");
+ final ImeVisibilityResult imeVisRes = mVisibilityStateComputer.computeState(windowState,
+ isSoftInputModeStateVisibleAllowed(unverifiedTargetSdkVersion, startInputFlags));
+ if (imeVisRes != null) {
+ switch (imeVisRes.getReason()) {
+ case SoftInputShowHideReason.SHOW_RESTORE_IME_VISIBILITY:
+ case SoftInputShowHideReason.SHOW_AUTO_EDITOR_FORWARD_NAV:
+ case SoftInputShowHideReason.SHOW_STATE_VISIBLE_FORWARD_NAV:
+ case SoftInputShowHideReason.SHOW_STATE_ALWAYS_VISIBLE:
if (editorInfo != null) {
res = startInputUncheckedLocked(cs, inputContext,
remoteAccessibilityInputConnection, editorInfo, startInputFlags,
@@ -3860,106 +3720,25 @@
imeDispatcher);
didStart = true;
}
- showCurrentInputImplicitLocked(windowToken,
- SoftInputShowHideReason.SHOW_AUTO_EDITOR_FORWARD_NAV);
- }
- break;
- case LayoutParams.SOFT_INPUT_STATE_UNCHANGED:
- if (DEBUG) {
- Slog.v(TAG, "Window asks to keep the input in whatever state it was last in");
- }
- // Do nothing.
- break;
- case LayoutParams.SOFT_INPUT_STATE_HIDDEN:
- if ((softInputMode & LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
- if (DEBUG) Slog.v(TAG, "Window asks to hide input going forward");
- hideCurrentInputLocked(mCurFocusedWindow, null /* statsToken */, 0 /* flags */,
- null /* resultReceiver */,
- SoftInputShowHideReason.HIDE_STATE_HIDDEN_FORWARD_NAV);
- }
- break;
- case LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN:
- if (!sameWindowFocused) {
- if (DEBUG) Slog.v(TAG, "Window asks to hide input");
- hideCurrentInputLocked(mCurFocusedWindow, null /* statsToken */, 0 /* flags */,
- null /* resultReceiver */,
- SoftInputShowHideReason.HIDE_ALWAYS_HIDDEN_STATE);
- }
- break;
- case LayoutParams.SOFT_INPUT_STATE_VISIBLE:
- if ((softInputMode & LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
- if (DEBUG) Slog.v(TAG, "Window asks to show input going forward");
- if (isSoftInputModeStateVisibleAllowed(
- unverifiedTargetSdkVersion, startInputFlags)) {
- if (editorInfo != null) {
- res = startInputUncheckedLocked(cs, inputContext,
- remoteAccessibilityInputConnection, editorInfo, startInputFlags,
- startInputReason, unverifiedTargetSdkVersion,
- imeDispatcher);
- didStart = true;
- }
- showCurrentInputImplicitLocked(windowToken,
- SoftInputShowHideReason.SHOW_STATE_VISIBLE_FORWARD_NAV);
- } else {
- Slog.e(TAG, "SOFT_INPUT_STATE_VISIBLE is ignored because"
- + " there is no focused view that also returns true from"
- + " View#onCheckIsTextEditor()");
- }
- }
- break;
- case LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE:
- if (DEBUG) Slog.v(TAG, "Window asks to always show input");
- if (isSoftInputModeStateVisibleAllowed(
- unverifiedTargetSdkVersion, startInputFlags)) {
- if (!sameWindowFocused) {
- if (editorInfo != null) {
- res = startInputUncheckedLocked(cs, inputContext,
- remoteAccessibilityInputConnection, editorInfo, startInputFlags,
- startInputReason, unverifiedTargetSdkVersion,
- imeDispatcher);
- didStart = true;
- }
- showCurrentInputImplicitLocked(windowToken,
- SoftInputShowHideReason.SHOW_STATE_ALWAYS_VISIBLE);
- }
- } else {
- Slog.e(TAG, "SOFT_INPUT_STATE_ALWAYS_VISIBLE is ignored because"
- + " there is no focused view that also returns true from"
- + " View#onCheckIsTextEditor()");
- }
- break;
- }
+ break;
+ }
+ mVisibilityApplier.applyImeVisibility(mCurFocusedWindow, null /* statsToken */,
+ imeVisRes.getState(), imeVisRes.getReason());
+
+ if (imeVisRes.getReason() == SoftInputShowHideReason.HIDE_UNSPECIFIED_WINDOW) {
+ // If focused display changed, we should unbind current method
+ // to make app window in previous display relayout after Ime
+ // window token removed.
+ // Note that we can trust client's display ID as long as it matches
+ // to the display ID obtained from the window.
+ if (cs.mSelfReportedDisplayId != mCurTokenDisplayId) {
+ mBindingController.unbindCurrentMethod();
+ }
+ }
+ }
if (!didStart) {
if (editorInfo != null) {
- if (sameWindowFocused) {
- // On previous platforms, when Dialogs re-gained focus, the Activity behind
- // would briefly gain focus first, and dismiss the IME.
- // On R that behavior has been fixed, but unfortunately apps have come
- // to rely on this behavior to hide the IME when the editor no longer has focus
- // To maintain compatibility, we are now hiding the IME when we don't have
- // an editor upon refocusing a window.
- if (startInputByWinGainedFocus) {
- if (DEBUG) Slog.v(TAG, "Same window without editor will hide input");
- hideCurrentInputLocked(mCurFocusedWindow, null /* statsToken */,
- 0 /* flags */, null /* resultReceiver */,
- SoftInputShowHideReason.HIDE_SAME_WINDOW_FOCUSED_WITHOUT_EDITOR);
- }
- }
- if (!isTextEditor && mInputShown && startInputByWinGainedFocus
- && mInputMethodDeviceConfigs.shouldHideImeWhenNoEditorFocus()) {
- // Hide the soft-keyboard when the system do nothing for softInputModeState
- // of the window being gained focus without an editor. This behavior benefits
- // to resolve some unexpected IME visible cases while that window with following
- // configurations being switched from an IME shown window:
- // 1) SOFT_INPUT_STATE_UNCHANGED state without an editor
- // 2) SOFT_INPUT_STATE_VISIBLE state without an editor
- // 3) SOFT_INPUT_STATE_ALWAYS_VISIBLE state without an editor
- if (DEBUG) Slog.v(TAG, "Window without editor will hide input");
- hideCurrentInputLocked(mCurFocusedWindow, null /* statsToken */, 0 /* flags */,
- null /* resultReceiver */,
- SoftInputShowHideReason.HIDE_WINDOW_GAINED_FOCUS_WITHOUT_EDITOR);
- }
res = startInputUncheckedLocked(cs, inputContext,
remoteAccessibilityInputConnection, editorInfo, startInputFlags,
startInputReason, unverifiedTargetSdkVersion,
@@ -3988,32 +3767,19 @@
// be made before input is started in it.
final ClientState cs = mClients.get(client.asBinder());
if (cs == null) {
- ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_SERVER_CLIENT_KNOWN);
+ ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_SERVER_CLIENT_KNOWN);
throw new IllegalArgumentException("unknown client " + client.asBinder());
}
- ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_CLIENT_KNOWN);
+ ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_SERVER_CLIENT_KNOWN);
if (!isImeClientFocused(mCurFocusedWindow, cs)) {
Slog.w(TAG, String.format("Ignoring %s of uid %d : %s", methodName, uid, client));
return false;
}
}
- ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_CLIENT_FOCUSED);
+ ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_SERVER_CLIENT_FOCUSED);
return true;
}
- private boolean shouldRestoreImeVisibility(IBinder windowToken,
- @SoftInputModeFlags int softInputMode) {
- switch (softInputMode & LayoutParams.SOFT_INPUT_MASK_STATE) {
- case LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN:
- return false;
- case LayoutParams.SOFT_INPUT_STATE_HIDDEN:
- if ((softInputMode & LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
- return false;
- }
- }
- return mWindowManagerInternal.shouldRestoreImeVisibility(windowToken);
- }
-
@GuardedBy("ImfLock.class")
private boolean canShowInputMethodPickerLocked(IInputMethodClient client) {
final int uid = Binder.getCallingUid();
@@ -4745,10 +4511,7 @@
mCurEditorInfo.dumpDebug(proto, CUR_ATTRIBUTE);
}
proto.write(CUR_ID, getCurIdLocked());
- proto.write(SHOW_REQUESTED, mShowRequested);
- proto.write(SHOW_EXPLICITLY_REQUESTED, mShowExplicitlyRequested);
- proto.write(SHOW_FORCED, mShowForced);
- proto.write(INPUT_SHOWN, mInputShown);
+ mVisibilityStateComputer.dumpDebug(proto, fieldId);
proto.write(IN_FULLSCREEN_MODE, mInFullscreenMode);
proto.write(CUR_TOKEN, Objects.toString(getCurTokenLocked()));
proto.write(CUR_TOKEN_DISPLAY_ID, mCurTokenDisplayId);
@@ -4760,8 +4523,6 @@
proto.write(BACK_DISPOSITION, mBackDisposition);
proto.write(IME_WINDOW_VISIBILITY, mImeWindowVis);
proto.write(SHOW_IME_WITH_HARD_KEYBOARD, mMenuController.getShowImeWithHardKeyboard());
- proto.write(ACCESSIBILITY_REQUESTING_NO_SOFT_KEYBOARD,
- mAccessibilityRequestingNoSoftKeyboard);
proto.end(token);
}
}
@@ -4792,28 +4553,14 @@
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.applyImeVisibility");
synchronized (ImfLock.class) {
if (!calledWithValidTokenLocked(token)) {
- ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_SERVER_APPLY_IME_VISIBILITY);
+ ImeTracker.forLogging().onFailed(statsToken,
+ ImeTracker.PHASE_SERVER_APPLY_IME_VISIBILITY);
return;
}
- if (!setVisible) {
- if (mCurClient != null) {
- ImeTracker.get().onProgress(statsToken,
- ImeTracker.PHASE_SERVER_APPLY_IME_VISIBILITY);
-
- mWindowManagerInternal.hideIme(
- mHideRequestWindowMap.get(windowToken),
- mCurClient.mSelfReportedDisplayId, statsToken);
- } else {
- ImeTracker.get().onFailed(statsToken,
- ImeTracker.PHASE_SERVER_APPLY_IME_VISIBILITY);
- }
- } else {
- ImeTracker.get().onProgress(statsToken,
- ImeTracker.PHASE_SERVER_APPLY_IME_VISIBILITY);
- // Send to window manager to show IME after IME layout finishes.
- mWindowManagerInternal.showImePostLayout(mShowRequestWindowMap.get(windowToken),
- statsToken);
- }
+ final IBinder requestToken = mVisibilityStateComputer.getWindowTokenFrom(windowToken);
+ mVisibilityApplier.applyImeVisibility(requestToken, statsToken,
+ setVisible ? ImeVisibilityStateComputer.STATE_SHOW_IME
+ : ImeVisibilityStateComputer.STATE_HIDE_IME);
}
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
@@ -4857,7 +4604,7 @@
/** Called right after {@link com.android.internal.inputmethod.IInputMethod#showSoftInput}. */
@GuardedBy("ImfLock.class")
- private void onShowHideSoftInputRequested(boolean show, IBinder requestToken,
+ void onShowHideSoftInputRequested(boolean show, IBinder requestToken,
@SoftInputShowHideReason int reason, @Nullable ImeTracker.Token statsToken) {
final WindowManagerInternal.ImeTargetInfo info =
mWindowManagerInternal.onToggleImeRequested(
@@ -4909,6 +4656,16 @@
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
+ @VisibleForTesting
+ ImeVisibilityStateComputer getVisibilityStateComputer() {
+ return mVisibilityStateComputer;
+ }
+
+ @VisibleForTesting
+ ImeVisibilityApplier getVisibilityApplier() {
+ return mVisibilityApplier;
+ }
+
@GuardedBy("ImfLock.class")
void setEnabledSessionLocked(SessionState session) {
if (mEnabledSession != session) {
@@ -4971,7 +4728,9 @@
// This is undocumented so far, but IMM#showInputMethodPicker() has been
// implemented so that auxiliary subtypes will be excluded when the soft
// keyboard is invisible.
- showAuxSubtypes = mInputShown;
+ synchronized (ImfLock.class) {
+ showAuxSubtypes = isInputShown();
+ }
break;
case InputMethodManager.SHOW_IM_PICKER_MODE_INCLUDE_AUXILIARY_SUBTYPES:
showAuxSubtypes = true;
@@ -5000,7 +4759,7 @@
synchronized (ImfLock.class) {
try {
if (mEnabledSession != null && mEnabledSession.mSession != null
- && !mShowRequested) {
+ && !isShowRequestedForCurrentWindow()) {
mEnabledSession.mSession.removeImeSurface();
}
} catch (RemoteException e) {
@@ -5545,6 +5304,53 @@
return mCurrentSubtype;
}
+ /**
+ * Returns the default {@link InputMethodInfo} for the specific userId.
+ * @param userId user ID to query.
+ */
+ @GuardedBy("ImfLock.class")
+ private InputMethodInfo queryDefaultInputMethodForUserIdLocked(@UserIdInt int userId) {
+ final String imeId = mSettings.getSelectedInputMethodForUser(userId);
+ if (TextUtils.isEmpty(imeId)) {
+ Slog.e(TAG, "No default input method found for userId " + userId);
+ return null;
+ }
+
+ InputMethodInfo curInputMethodInfo;
+ if (userId == mSettings.getCurrentUserId()
+ && (curInputMethodInfo = mMethodMap.get(imeId)) != null) {
+ // clone the InputMethodInfo before returning.
+ return new InputMethodInfo(curInputMethodInfo);
+ }
+
+ final ArrayMap<String, List<InputMethodSubtype>> additionalSubtypeMap = new ArrayMap<>();
+ AdditionalSubtypeUtils.load(additionalSubtypeMap, userId);
+ Context userAwareContext =
+ mContext.createContextAsUser(UserHandle.of(userId), 0 /* flags */);
+
+ final int flags = PackageManager.GET_META_DATA
+ | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
+ | PackageManager.MATCH_DIRECT_BOOT_AUTO;
+ final List<ResolveInfo> services =
+ userAwareContext.getPackageManager().queryIntentServicesAsUser(
+ new Intent(InputMethod.SERVICE_INTERFACE),
+ PackageManager.ResolveInfoFlags.of(flags),
+ userId);
+ for (ResolveInfo ri : services) {
+ final String imeIdResolved = InputMethodInfo.computeId(ri);
+ if (imeId.equals(imeIdResolved)) {
+ try {
+ return new InputMethodInfo(
+ userAwareContext, ri, additionalSubtypeMap.get(imeId));
+ } catch (Exception e) {
+ Slog.wtf(TAG, "Unable to load input method " + imeId, e);
+ }
+ }
+ }
+ // we didn't find the InputMethodInfo for imeId. This shouldn't happen.
+ Slog.e(TAG, "Error while locating input method info for imeId: " + imeId);
+ return null;
+ }
private ArrayMap<String, InputMethodInfo> queryMethodMapForUser(@UserIdInt int userId) {
final ArrayMap<String, InputMethodInfo> methodMap = new ArrayMap<>();
final ArrayList<InputMethodInfo> methodList = new ArrayList<>();
@@ -5988,14 +5794,10 @@
method = getCurMethodLocked();
p.println(" mCurMethod=" + getCurMethodLocked());
p.println(" mEnabledSession=" + mEnabledSession);
- p.println(" mShowRequested=" + mShowRequested
- + " mShowExplicitlyRequested=" + mShowExplicitlyRequested
- + " mShowForced=" + mShowForced
- + " mInputShown=" + mInputShown);
+ mVisibilityStateComputer.dump(pw);
p.println(" mInFullscreenMode=" + mInFullscreenMode);
p.println(" mSystemReady=" + mSystemReady + " mInteractive=" + mIsInteractive);
p.println(" mSettingsObserver=" + mSettingsObserver);
- p.println(" mImeHiddenByDisplayPolicy=" + mImeHiddenByDisplayPolicy);
p.println(" mStylusIds=" + (mStylusIds != null
? Arrays.toString(mStylusIds.toArray()) : ""));
p.println(" mSwitchingController:");
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodUtils.java b/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
index be99bfb..559eb53 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
@@ -330,11 +330,17 @@
@Nullable
private String getString(@NonNull String key, @Nullable String defaultValue) {
+ return getStringForUser(key, defaultValue, mCurrentUserId);
+ }
+
+ @Nullable
+ private String getStringForUser(
+ @NonNull String key, @Nullable String defaultValue, @UserIdInt int userId) {
final String result;
if (mCopyOnWrite && mCopyOnWriteDataStore.containsKey(key)) {
result = mCopyOnWriteDataStore.get(key);
} else {
- result = Settings.Secure.getStringForUser(mResolver, key, mCurrentUserId);
+ result = Settings.Secure.getStringForUser(mResolver, key, userId);
}
return result != null ? result : defaultValue;
}
@@ -741,6 +747,16 @@
return imi;
}
+ @Nullable
+ String getSelectedInputMethodForUser(@UserIdInt int userId) {
+ final String imi =
+ getStringForUser(Settings.Secure.DEFAULT_INPUT_METHOD, null, userId);
+ if (DEBUG) {
+ Slog.d(TAG, "getSelectedInputMethodForUserStr: " + imi);
+ }
+ return imi;
+ }
+
void putDefaultVoiceInputMethod(String imeId) {
if (DEBUG) {
Slog.d(TAG, "putDefaultVoiceInputMethodStr: " + imeId + ", " + mCurrentUserId);
diff --git a/services/core/java/com/android/server/location/LocationManagerService.java b/services/core/java/com/android/server/location/LocationManagerService.java
index b4c9596..1cc958b 100644
--- a/services/core/java/com/android/server/location/LocationManagerService.java
+++ b/services/core/java/com/android/server/location/LocationManagerService.java
@@ -202,6 +202,9 @@
@Override
public void onUserStarting(TargetUser user) {
mUserInfoHelper.onUserStarted(user.getUserIdentifier());
+
+ // log location enabled state on start to minimize coverage loss
+ mService.logLocationEnabledState();
}
@Override
@@ -553,6 +556,7 @@
}
EVENT_LOG.logLocationEnabled(userId, enabled);
+ logLocationEnabledState();
Intent intent = new Intent(LocationManager.MODE_CHANGED_ACTION)
.putExtra(LocationManager.EXTRA_LOCATION_ENABLED, enabled)
@@ -563,6 +567,20 @@
refreshAppOpsRestrictions(userId);
}
+ private void logLocationEnabledState() {
+ boolean locationEnabled = false;
+ // Location setting is considered on if it is enabled for any one user
+ int[] runningUserIds = mInjector.getUserInfoHelper().getRunningUserIds();
+ for (int userId : runningUserIds) {
+ locationEnabled = mInjector.getSettingsHelper().isLocationEnabled(userId);
+ if (locationEnabled) {
+ break;
+ }
+ }
+ mInjector.getLocationUsageLogger()
+ .logLocationEnabledStateChanged(locationEnabled);
+ }
+
@Override
public int getGnssYearOfHardware() {
return mGnssManagerService == null ? 0 : mGnssManagerService.getGnssYearOfHardware();
diff --git a/services/core/java/com/android/server/location/injector/LocationUsageLogger.java b/services/core/java/com/android/server/location/injector/LocationUsageLogger.java
index af21bcb..a9701b3 100644
--- a/services/core/java/com/android/server/location/injector/LocationUsageLogger.java
+++ b/services/core/java/com/android/server/location/injector/LocationUsageLogger.java
@@ -122,6 +122,13 @@
}
}
+ /**
+ * Log a location enabled state change event.
+ */
+ public synchronized void logLocationEnabledStateChanged(boolean enabled) {
+ FrameworkStatsLog.write(FrameworkStatsLog.LOCATION_ENABLED_STATE_CHANGED, enabled);
+ }
+
private static int bucketizeProvider(String provider) {
if (LocationManager.NETWORK_PROVIDER.equals(provider)) {
return LocationStatsEnums.PROVIDER_NETWORK;
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 121b7c8..31b8ef2 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -1156,18 +1156,21 @@
@Override
public void setBoolean(String key, boolean value, int userId) {
checkWritePermission();
+ Objects.requireNonNull(key);
mStorage.setBoolean(key, value, userId);
}
@Override
public void setLong(String key, long value, int userId) {
checkWritePermission();
+ Objects.requireNonNull(key);
mStorage.setLong(key, value, userId);
}
@Override
public void setString(String key, String value, int userId) {
checkWritePermission();
+ Objects.requireNonNull(key);
mStorage.setString(key, value, userId);
}
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
index 2c28af1..434c0d7 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
@@ -62,6 +62,7 @@
import java.util.Arrays;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
/**
* Storage for the lock settings service.
@@ -886,12 +887,15 @@
if (!(obj instanceof CacheKey))
return false;
CacheKey o = (CacheKey) obj;
- return userId == o.userId && type == o.type && key.equals(o.key);
+ return userId == o.userId && type == o.type && Objects.equals(key, o.key);
}
@Override
public int hashCode() {
- return key.hashCode() ^ userId ^ type;
+ int hashCode = Objects.hashCode(key);
+ hashCode = 31 * hashCode + userId;
+ hashCode = 31 * hashCode + type;
+ return hashCode;
}
}
}
diff --git a/services/core/java/com/android/server/media/BluetoothRouteProvider.java b/services/core/java/com/android/server/media/BluetoothRouteProvider.java
index e1a990d..ab59f87 100644
--- a/services/core/java/com/android/server/media/BluetoothRouteProvider.java
+++ b/services/core/java/com/android/server/media/BluetoothRouteProvider.java
@@ -27,6 +27,7 @@
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHearingAid;
import android.bluetooth.BluetoothLeAudio;
+import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -59,17 +60,9 @@
private static final String HEARING_AID_ROUTE_ID_PREFIX = "HEARING_AID_";
private static final String LE_AUDIO_ROUTE_ID_PREFIX = "LE_AUDIO_";
- @SuppressWarnings("WeakerAccess") /* synthetic access */
// Maps hardware address to BluetoothRouteInfo
- final Map<String, BluetoothRouteInfo> mBluetoothRoutes = new HashMap<>();
- @SuppressWarnings("WeakerAccess") /* synthetic access */
- final List<BluetoothRouteInfo> mActiveRoutes = new ArrayList<>();
- @SuppressWarnings("WeakerAccess") /* synthetic access */
- BluetoothA2dp mA2dpProfile;
- @SuppressWarnings("WeakerAccess") /* synthetic access */
- BluetoothHearingAid mHearingAidProfile;
- @SuppressWarnings("WeakerAccess") /* synthetic access */
- BluetoothLeAudio mLeAudioProfile;
+ private final Map<String, BluetoothRouteInfo> mBluetoothRoutes = new HashMap<>();
+ private final List<BluetoothRouteInfo> mActiveRoutes = new ArrayList<>();
// Route type -> volume map
private final SparseIntArray mVolumeMap = new SparseIntArray();
@@ -78,11 +71,17 @@
private final BluetoothAdapter mBluetoothAdapter;
private final BluetoothRoutesUpdatedListener mListener;
private final AudioManager mAudioManager;
- private final Map<String, BluetoothEventReceiver> mEventReceiverMap = new HashMap<>();
- private final IntentFilter mIntentFilter = new IntentFilter();
- private final BroadcastReceiver mBroadcastReceiver = new BluetoothBroadcastReceiver();
private final BluetoothProfileListener mProfileListener = new BluetoothProfileListener();
+ private final AdapterStateChangedReceiver mAdapterStateChangedReceiver =
+ new AdapterStateChangedReceiver();
+ private final DeviceStateChangedReceiver mDeviceStateChangedReceiver =
+ new DeviceStateChangedReceiver();
+
+ private BluetoothA2dp mA2dpProfile;
+ private BluetoothHearingAid mHearingAidProfile;
+ private BluetoothLeAudio mLeAudioProfile;
+
/**
* Create an instance of {@link BluetoothRouteProvider}.
* It may return {@code null} if Bluetooth is not supported on this hardware platform.
@@ -93,7 +92,9 @@
Objects.requireNonNull(context);
Objects.requireNonNull(listener);
- BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
+ BluetoothManager bluetoothManager = (BluetoothManager)
+ context.getSystemService(Context.BLUETOOTH_SERVICE);
+ BluetoothAdapter btAdapter = bluetoothManager.getAdapter();
if (btAdapter == null) {
return null;
}
@@ -109,32 +110,45 @@
buildBluetoothRoutes();
}
- public void start(UserHandle user) {
+ /**
+ * Registers listener to bluetooth status changes as the provided user.
+ *
+ * The registered receiver listens to {@link BluetoothA2dp#ACTION_ACTIVE_DEVICE_CHANGED} and
+ * {@link BluetoothA2dp#ACTION_CONNECTION_STATE_CHANGED } events for {@link BluetoothProfile#A2DP},
+ * {@link BluetoothProfile#HEARING_AID}, and {@link BluetoothProfile#LE_AUDIO} bluetooth profiles.
+ *
+ * @param user {@code UserHandle} as which receiver is registered
+ */
+ void start(UserHandle user) {
mBluetoothAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.A2DP);
mBluetoothAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.HEARING_AID);
mBluetoothAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.LE_AUDIO);
- // Bluetooth on/off broadcasts
- addEventReceiver(BluetoothAdapter.ACTION_STATE_CHANGED, new AdapterStateChangedReceiver());
+ IntentFilter adapterStateChangedIntentFilter = new IntentFilter();
- DeviceStateChangedReceiver deviceStateChangedReceiver = new DeviceStateChangedReceiver();
- addEventReceiver(BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED, deviceStateChangedReceiver);
- addEventReceiver(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED, deviceStateChangedReceiver);
- addEventReceiver(BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED,
- deviceStateChangedReceiver);
- addEventReceiver(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED,
- deviceStateChangedReceiver);
- addEventReceiver(BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED,
- deviceStateChangedReceiver);
- addEventReceiver(BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED,
- deviceStateChangedReceiver);
+ adapterStateChangedIntentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
+ mContext.registerReceiverAsUser(mAdapterStateChangedReceiver, user,
+ adapterStateChangedIntentFilter, null, null);
- mContext.registerReceiverAsUser(mBroadcastReceiver, user,
- mIntentFilter, null, null);
+ IntentFilter deviceStateChangedIntentFilter = new IntentFilter();
+
+ deviceStateChangedIntentFilter.addAction(BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED);
+ deviceStateChangedIntentFilter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
+ deviceStateChangedIntentFilter.addAction(BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED);
+ deviceStateChangedIntentFilter.addAction(
+ BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED);
+ deviceStateChangedIntentFilter.addAction(
+ BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED);
+ deviceStateChangedIntentFilter.addAction(
+ BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED);
+
+ mContext.registerReceiverAsUser(mDeviceStateChangedReceiver, user,
+ deviceStateChangedIntentFilter, null, null);
}
- public void stop() {
- mContext.unregisterReceiver(mBroadcastReceiver);
+ void stop() {
+ mContext.unregisterReceiver(mAdapterStateChangedReceiver);
+ mContext.unregisterReceiver(mDeviceStateChangedReceiver);
}
/**
@@ -144,7 +158,7 @@
* @param routeId the id of the Bluetooth device. {@code null} denotes to clear the use of
* BT routes.
*/
- public void transferTo(@Nullable String routeId) {
+ void transferTo(@Nullable String routeId) {
if (routeId == null) {
clearActiveDevices();
return;
@@ -158,10 +172,22 @@
}
if (mBluetoothAdapter != null) {
- mBluetoothAdapter.setActiveDevice(btRouteInfo.btDevice, ACTIVE_DEVICE_AUDIO);
+ mBluetoothAdapter.setActiveDevice(btRouteInfo.mBtDevice, ACTIVE_DEVICE_AUDIO);
}
}
+ private BluetoothRouteInfo findBluetoothRouteWithRouteId(String routeId) {
+ if (routeId == null) {
+ return null;
+ }
+ for (BluetoothRouteInfo btRouteInfo : mBluetoothRoutes.values()) {
+ if (TextUtils.equals(btRouteInfo.mRoute.getId(), routeId)) {
+ return btRouteInfo;
+ }
+ }
+ return null;
+ }
+
/**
* Clears the active device for all known profiles.
*/
@@ -171,11 +197,6 @@
}
}
- private void addEventReceiver(String action, BluetoothEventReceiver eventReceiver) {
- mEventReceiverMap.put(action, eventReceiver);
- mIntentFilter.addAction(action);
- }
-
private void buildBluetoothRoutes() {
mBluetoothRoutes.clear();
Set<BluetoothDevice> bondedDevices = mBluetoothAdapter.getBondedDevices();
@@ -183,7 +204,7 @@
for (BluetoothDevice device : bondedDevices) {
if (device.isConnected()) {
BluetoothRouteInfo newBtRoute = createBluetoothRoute(device);
- if (newBtRoute.connectedProfiles.size() > 0) {
+ if (newBtRoute.mConnectedProfiles.size() > 0) {
mBluetoothRoutes.put(device.getAddress(), newBtRoute);
}
}
@@ -195,14 +216,14 @@
MediaRoute2Info getSelectedRoute() {
// For now, active routes can be multiple only when a pair of hearing aid devices is active.
// Let the first active device represent them.
- return (mActiveRoutes.isEmpty() ? null : mActiveRoutes.get(0).route);
+ return (mActiveRoutes.isEmpty() ? null : mActiveRoutes.get(0).mRoute);
}
@NonNull
List<MediaRoute2Info> getTransferableRoutes() {
List<MediaRoute2Info> routes = getAllBluetoothRoutes();
for (BluetoothRouteInfo btRoute : mActiveRoutes) {
- routes.remove(btRoute.route);
+ routes.remove(btRoute.mRoute);
}
return routes;
}
@@ -220,33 +241,21 @@
for (BluetoothRouteInfo btRoute : mBluetoothRoutes.values()) {
// A pair of hearing aid devices or having the same hardware address
- if (routeIds.contains(btRoute.route.getId())) {
+ if (routeIds.contains(btRoute.mRoute.getId())) {
continue;
}
- routes.add(btRoute.route);
- routeIds.add(btRoute.route.getId());
+ routes.add(btRoute.mRoute);
+ routeIds.add(btRoute.mRoute.getId());
}
return routes;
}
- BluetoothRouteInfo findBluetoothRouteWithRouteId(String routeId) {
- if (routeId == null) {
- return null;
- }
- for (BluetoothRouteInfo btRouteInfo : mBluetoothRoutes.values()) {
- if (TextUtils.equals(btRouteInfo.route.getId(), routeId)) {
- return btRouteInfo;
- }
- }
- return null;
- }
-
/**
* Updates the volume for {@link AudioManager#getDevicesForStream(int) devices}.
*
* @return true if devices can be handled by the provider.
*/
- public boolean updateVolumeForDevices(int devices, int volume) {
+ boolean updateVolumeForDevices(int devices, int volume) {
int routeType;
if ((devices & (AudioSystem.DEVICE_OUT_HEARING_AID)) != 0) {
routeType = MediaRoute2Info.TYPE_HEARING_AID;
@@ -263,10 +272,10 @@
boolean shouldNotify = false;
for (BluetoothRouteInfo btRoute : mActiveRoutes) {
- if (btRoute.route.getType() != routeType) {
+ if (btRoute.mRoute.getType() != routeType) {
continue;
}
- btRoute.route = new MediaRoute2Info.Builder(btRoute.route)
+ btRoute.mRoute = new MediaRoute2Info.Builder(btRoute.mRoute)
.setVolume(volume)
.build();
shouldNotify = true;
@@ -285,7 +294,7 @@
private BluetoothRouteInfo createBluetoothRoute(BluetoothDevice device) {
BluetoothRouteInfo newBtRoute = new BluetoothRouteInfo();
- newBtRoute.btDevice = device;
+ newBtRoute.mBtDevice = device;
String routeId = device.getAddress();
String deviceName = device.getName();
@@ -293,26 +302,26 @@
deviceName = mContext.getResources().getText(R.string.unknownName).toString();
}
int type = MediaRoute2Info.TYPE_BLUETOOTH_A2DP;
- newBtRoute.connectedProfiles = new SparseBooleanArray();
+ newBtRoute.mConnectedProfiles = new SparseBooleanArray();
if (mA2dpProfile != null && mA2dpProfile.getConnectedDevices().contains(device)) {
- newBtRoute.connectedProfiles.put(BluetoothProfile.A2DP, true);
+ newBtRoute.mConnectedProfiles.put(BluetoothProfile.A2DP, true);
}
if (mHearingAidProfile != null
&& mHearingAidProfile.getConnectedDevices().contains(device)) {
- newBtRoute.connectedProfiles.put(BluetoothProfile.HEARING_AID, true);
+ newBtRoute.mConnectedProfiles.put(BluetoothProfile.HEARING_AID, true);
// Intentionally assign the same ID for a pair of devices to publish only one of them.
routeId = HEARING_AID_ROUTE_ID_PREFIX + mHearingAidProfile.getHiSyncId(device);
type = MediaRoute2Info.TYPE_HEARING_AID;
}
if (mLeAudioProfile != null
&& mLeAudioProfile.getConnectedDevices().contains(device)) {
- newBtRoute.connectedProfiles.put(BluetoothProfile.LE_AUDIO, true);
+ newBtRoute.mConnectedProfiles.put(BluetoothProfile.LE_AUDIO, true);
routeId = LE_AUDIO_ROUTE_ID_PREFIX + mLeAudioProfile.getGroupId(device);
type = MediaRoute2Info.TYPE_BLE_HEADSET;
}
// Current volume will be set when connected.
- newBtRoute.route = new MediaRoute2Info.Builder(routeId, deviceName)
+ newBtRoute.mRoute = new MediaRoute2Info.Builder(routeId, deviceName)
.addFeature(MediaRoute2Info.FEATURE_LIVE_AUDIO)
.addFeature(MediaRoute2Info.FEATURE_LOCAL_PLAYBACK)
.setConnectionState(MediaRoute2Info.CONNECTION_STATE_DISCONNECTED)
@@ -332,18 +341,18 @@
Slog.w(TAG, "setRouteConnectionState: route shouldn't be null");
return;
}
- if (btRoute.route.getConnectionState() == state) {
+ if (btRoute.mRoute.getConnectionState() == state) {
return;
}
- MediaRoute2Info.Builder builder = new MediaRoute2Info.Builder(btRoute.route)
+ MediaRoute2Info.Builder builder = new MediaRoute2Info.Builder(btRoute.mRoute)
.setConnectionState(state);
builder.setType(btRoute.getRouteType());
if (state == MediaRoute2Info.CONNECTION_STATE_CONNECTED) {
builder.setVolume(mVolumeMap.get(btRoute.getRouteType(), 0));
}
- btRoute.route = builder.build();
+ btRoute.mRoute = builder.build();
}
private void addActiveRoute(BluetoothRouteInfo btRoute) {
@@ -352,7 +361,7 @@
return;
}
if (DEBUG) {
- Log.d(TAG, "Adding active route: " + btRoute.route);
+ Log.d(TAG, "Adding active route: " + btRoute.mRoute);
}
if (mActiveRoutes.contains(btRoute)) {
Slog.w(TAG, "addActiveRoute: btRoute is already added.");
@@ -364,7 +373,7 @@
private void removeActiveRoute(BluetoothRouteInfo btRoute) {
if (DEBUG) {
- Log.d(TAG, "Removing active route: " + btRoute.route);
+ Log.d(TAG, "Removing active route: " + btRoute.mRoute);
}
if (mActiveRoutes.remove(btRoute)) {
setRouteConnectionState(btRoute, STATE_DISCONNECTED);
@@ -378,7 +387,7 @@
Iterator<BluetoothRouteInfo> iter = mActiveRoutes.iterator();
while (iter.hasNext()) {
BluetoothRouteInfo btRoute = iter.next();
- if (btRoute.route.getType() == type) {
+ if (btRoute.mRoute.getType() == type) {
iter.remove();
setRouteConnectionState(btRoute, STATE_DISCONNECTED);
}
@@ -398,46 +407,31 @@
// A bluetooth route with the same route ID should be added.
for (BluetoothRouteInfo btRoute : mBluetoothRoutes.values()) {
- if (TextUtils.equals(btRoute.route.getId(), activeBtRoute.route.getId())
- && !TextUtils.equals(btRoute.btDevice.getAddress(),
- activeBtRoute.btDevice.getAddress())) {
+ if (TextUtils.equals(btRoute.mRoute.getId(), activeBtRoute.mRoute.getId())
+ && !TextUtils.equals(btRoute.mBtDevice.getAddress(),
+ activeBtRoute.mBtDevice.getAddress())) {
addActiveRoute(btRoute);
}
}
}
- private void addActiveHearingAidDevices(BluetoothDevice device) {
- if (DEBUG) {
- Log.d(TAG, "Setting active hearing aid devices. device=" + device);
- }
-
- addActiveDevices(device);
- }
-
- private void addActiveLeAudioDevices(BluetoothDevice device) {
- if (DEBUG) {
- Log.d(TAG, "Setting active le audio devices. device=" + device);
- }
-
- addActiveDevices(device);
- }
interface BluetoothRoutesUpdatedListener {
void onBluetoothRoutesUpdated(@NonNull List<MediaRoute2Info> routes);
}
- private class BluetoothRouteInfo {
- public BluetoothDevice btDevice;
- public MediaRoute2Info route;
- public SparseBooleanArray connectedProfiles;
+ private static class BluetoothRouteInfo {
+ private BluetoothDevice mBtDevice;
+ private MediaRoute2Info mRoute;
+ private SparseBooleanArray mConnectedProfiles;
@MediaRoute2Info.Type
int getRouteType() {
// Let hearing aid profile have a priority.
- if (connectedProfiles.get(BluetoothProfile.HEARING_AID, false)) {
+ if (mConnectedProfiles.get(BluetoothProfile.HEARING_AID, false)) {
return MediaRoute2Info.TYPE_HEARING_AID;
}
- if (connectedProfiles.get(BluetoothProfile.LE_AUDIO, false)) {
+ if (mConnectedProfiles.get(BluetoothProfile.LE_AUDIO, false)) {
return MediaRoute2Info.TYPE_BLE_HEADSET;
}
@@ -447,6 +441,7 @@
// These callbacks run on the main thread.
private final class BluetoothProfileListener implements BluetoothProfile.ServiceListener {
+ @Override
public void onServiceConnected(int profile, BluetoothProfile proxy) {
List<BluetoothDevice> activeDevices;
switch (profile) {
@@ -480,6 +475,7 @@
notifyBluetoothRoutesUpdated();
}
+ @Override
public void onServiceDisconnected(int profile) {
switch (profile) {
case BluetoothProfile.A2DP:
@@ -496,25 +492,10 @@
}
}
}
- private class BluetoothBroadcastReceiver extends BroadcastReceiver {
+
+ private class AdapterStateChangedReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE, android.bluetooth.BluetoothDevice.class);
-
- BluetoothEventReceiver receiver = mEventReceiverMap.get(action);
- if (receiver != null) {
- receiver.onReceive(context, intent, device);
- }
- }
- }
-
- private interface BluetoothEventReceiver {
- void onReceive(Context context, Intent intent, BluetoothDevice device);
- }
-
- private class AdapterStateChangedReceiver implements BluetoothEventReceiver {
- public void onReceive(Context context, Intent intent, BluetoothDevice device) {
int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
if (state == BluetoothAdapter.STATE_OFF
|| state == BluetoothAdapter.STATE_TURNING_OFF) {
@@ -529,9 +510,12 @@
}
}
- private class DeviceStateChangedReceiver implements BluetoothEventReceiver {
+ private class DeviceStateChangedReceiver extends BroadcastReceiver {
@Override
- public void onReceive(Context context, Intent intent, BluetoothDevice device) {
+ public void onReceive(Context context, Intent intent) {
+ BluetoothDevice device = intent.getParcelableExtra(
+ BluetoothDevice.EXTRA_DEVICE, android.bluetooth.BluetoothDevice.class);
+
switch (intent.getAction()) {
case BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED:
clearActiveRoutesWithType(MediaRoute2Info.TYPE_BLUETOOTH_A2DP);
@@ -543,14 +527,22 @@
case BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED:
clearActiveRoutesWithType(MediaRoute2Info.TYPE_HEARING_AID);
if (device != null) {
- addActiveHearingAidDevices(device);
+ if (DEBUG) {
+ Log.d(TAG, "Setting active hearing aid devices. device=" + device);
+ }
+
+ addActiveDevices(device);
}
notifyBluetoothRoutesUpdated();
break;
case BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED:
clearActiveRoutesWithType(MediaRoute2Info.TYPE_BLE_HEADSET);
if (device != null) {
- addActiveLeAudioDevices(device);
+ if (DEBUG) {
+ Log.d(TAG, "Setting active le audio devices. device=" + device);
+ }
+
+ addActiveDevices(device);
}
notifyBluetoothRoutesUpdated();
break;
@@ -573,18 +565,18 @@
if (state == BluetoothProfile.STATE_CONNECTED) {
if (btRoute == null) {
btRoute = createBluetoothRoute(device);
- if (btRoute.connectedProfiles.size() > 0) {
+ if (btRoute.mConnectedProfiles.size() > 0) {
mBluetoothRoutes.put(device.getAddress(), btRoute);
notifyBluetoothRoutesUpdated();
}
} else {
- btRoute.connectedProfiles.put(profile, true);
+ btRoute.mConnectedProfiles.put(profile, true);
}
} else if (state == BluetoothProfile.STATE_DISCONNECTING
|| state == BluetoothProfile.STATE_DISCONNECTED) {
if (btRoute != null) {
- btRoute.connectedProfiles.delete(profile);
- if (btRoute.connectedProfiles.size() == 0) {
+ btRoute.mConnectedProfiles.delete(profile);
+ if (btRoute.mConnectedProfiles.size() == 0) {
removeActiveRoute(mBluetoothRoutes.remove(device.getAddress()));
notifyBluetoothRoutesUpdated();
}
diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
index 9466a6f5..ed76dec 100644
--- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
@@ -63,6 +63,10 @@
private static final String TAG = "MR2SystemProvider";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ private static final ComponentName COMPONENT_NAME = new ComponentName(
+ SystemMediaRoute2Provider.class.getPackage().getName(),
+ SystemMediaRoute2Provider.class.getName());
+
static final String DEFAULT_ROUTE_ID = "DEFAULT_ROUTE";
static final String DEVICE_ROUTE_ID = "DEVICE_ROUTE";
static final String SYSTEM_SESSION_ID = "SYSTEM_SESSION";
@@ -74,17 +78,12 @@
private final UserHandle mUser;
private final BluetoothRouteProvider mBtRouteProvider;
- private static ComponentName sComponentName = new ComponentName(
- SystemMediaRoute2Provider.class.getPackage().getName(),
- SystemMediaRoute2Provider.class.getName());
-
private String mSelectedRouteId;
// For apps without MODIFYING_AUDIO_ROUTING permission.
// This should be the currently selected route.
MediaRoute2Info mDefaultRoute;
MediaRoute2Info mDeviceRoute;
RoutingSessionInfo mDefaultSessionInfo;
- final AudioRoutesInfo mCurAudioRoutesInfo = new AudioRoutesInfo();
int mDeviceVolume;
private final AudioManagerBroadcastReceiver mAudioReceiver =
@@ -108,7 +107,7 @@
};
SystemMediaRoute2Provider(Context context, UserHandle user) {
- super(sComponentName);
+ super(COMPONENT_NAME);
mIsSystemRouteProvider = true;
mContext = context;
@@ -275,7 +274,6 @@
int name = R.string.default_audio_route_name;
int type = TYPE_BUILTIN_SPEAKER;
if (newRoutes != null) {
- mCurAudioRoutesInfo.mainType = newRoutes.mainType;
if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADPHONES) != 0) {
type = TYPE_WIRED_HEADPHONES;
name = com.android.internal.R.string.default_audio_route_name_headphones;
diff --git a/services/core/java/com/android/server/media/projection/TEST_MAPPING b/services/core/java/com/android/server/media/projection/TEST_MAPPING
new file mode 100644
index 0000000..a792498
--- /dev/null
+++ b/services/core/java/com/android/server/media/projection/TEST_MAPPING
@@ -0,0 +1,18 @@
+{
+ "presubmit": [
+ {
+ "name": "MediaProjectionTests",
+ "options": [
+ {
+ "exclude-annotation": "android.platform.test.annotations.FlakyTest"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ },
+ {
+ "exclude-annotation": "org.junit.Ignore"
+ }
+ ]
+ }
+ ]
+}
diff --git a/services/core/java/com/android/server/NetworkManagementInternal.java b/services/core/java/com/android/server/net/NetworkManagementInternal.java
similarity index 96%
rename from services/core/java/com/android/server/NetworkManagementInternal.java
rename to services/core/java/com/android/server/net/NetworkManagementInternal.java
index f53c454..4926960 100644
--- a/services/core/java/com/android/server/NetworkManagementInternal.java
+++ b/services/core/java/com/android/server/net/NetworkManagementInternal.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server;
+package com.android.server.net;
/**
* NetworkManagement local system service interface.
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/net/NetworkManagementService.java
similarity index 99%
rename from services/core/java/com/android/server/NetworkManagementService.java
rename to services/core/java/com/android/server/net/NetworkManagementService.java
index fc26f09..acfa665 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/net/NetworkManagementService.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server;
+package com.android.server.net;
import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
import static android.net.ConnectivityManager.FIREWALL_CHAIN_DOZABLE;
@@ -82,6 +82,8 @@
import com.android.internal.util.Preconditions;
import com.android.net.module.util.NetdUtils;
import com.android.net.module.util.NetdUtils.ModifyOperation;
+import com.android.server.FgThread;
+import com.android.server.LocalServices;
import com.google.android.collect.Maps;
diff --git a/services/core/java/com/android/server/net/TEST_MAPPING b/services/core/java/com/android/server/net/TEST_MAPPING
index 4ccf09e..e0376ed 100644
--- a/services/core/java/com/android/server/net/TEST_MAPPING
+++ b/services/core/java/com/android/server/net/TEST_MAPPING
@@ -15,7 +15,7 @@
"presubmit": [
{
"name": "FrameworksServicesTests",
- "file_patterns": ["(/|^)NetworkPolicy[^/]*\\.java"],
+ "file_patterns": ["(/|^)Network(Policy|Management)[^/]*\\.java"],
"options": [
{
"include-filter": "com.android.server.net."
diff --git a/services/core/java/com/android/server/notification/NotificationShellCmd.java b/services/core/java/com/android/server/notification/NotificationShellCmd.java
index 628a322..dc0cf4e 100644
--- a/services/core/java/com/android/server/notification/NotificationShellCmd.java
+++ b/services/core/java/com/android/server/notification/NotificationShellCmd.java
@@ -540,16 +540,16 @@
if ("broadcast".equals(intentKind)) {
pi = PendingIntent.getBroadcastAsUser(
context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT
- | PendingIntent.FLAG_MUTABLE_UNAUDITED,
+ | PendingIntent.FLAG_IMMUTABLE,
UserHandle.CURRENT);
} else if ("service".equals(intentKind)) {
pi = PendingIntent.getService(
context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT
- | PendingIntent.FLAG_MUTABLE_UNAUDITED);
+ | PendingIntent.FLAG_IMMUTABLE);
} else {
pi = PendingIntent.getActivityAsUser(
context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT
- | PendingIntent.FLAG_MUTABLE_UNAUDITED, null,
+ | PendingIntent.FLAG_IMMUTABLE, null,
UserHandle.CURRENT);
}
builder.setContentIntent(pi);
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 5ab9f38..69ea559 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -108,7 +108,7 @@
@VisibleForTesting
static final int NOTIFICATION_CHANNEL_COUNT_LIMIT = 5000;
@VisibleForTesting
- static final int NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT = 50000;
+ static final int NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT = 6000;
private static final int NOTIFICATION_PREFERENCES_PULL_LIMIT = 1000;
private static final int NOTIFICATION_CHANNEL_PULL_LIMIT = 2000;
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index 71593e1..5e62b56 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -138,7 +138,7 @@
this.activeApexChanged = activeApexChanged;
}
- private ActiveApexInfo(ApexInfo apexInfo) {
+ public ActiveApexInfo(ApexInfo apexInfo) {
this(
apexInfo.moduleName,
new File(Environment.getApexDirectory() + File.separator
diff --git a/services/core/java/com/android/server/pm/AppsFilterImpl.java b/services/core/java/com/android/server/pm/AppsFilterImpl.java
index 5ff1909b..ac8ff21 100644
--- a/services/core/java/com/android/server/pm/AppsFilterImpl.java
+++ b/services/core/java/com/android/server/pm/AppsFilterImpl.java
@@ -32,6 +32,7 @@
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_MANAGER_APPS_FILTER_CACHE_UPDATE_REPORTED__EVENT_TYPE__PACKAGE_DELETED;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_MANAGER_APPS_FILTER_CACHE_UPDATE_REPORTED__EVENT_TYPE__PACKAGE_REPLACED;
import static com.android.server.pm.AppsFilterUtils.canQueryAsInstaller;
+import static com.android.server.pm.AppsFilterUtils.canQueryAsUpdateOwner;
import static com.android.server.pm.AppsFilterUtils.canQueryViaComponents;
import static com.android.server.pm.AppsFilterUtils.canQueryViaPackage;
import static com.android.server.pm.AppsFilterUtils.canQueryViaUsesLibrary;
@@ -670,7 +671,8 @@
}
}
if (canQueryViaPackage(existingPkg, newPkg)
- || canQueryAsInstaller(existingSetting, newPkg)) {
+ || canQueryAsInstaller(existingSetting, newPkg)
+ || canQueryAsUpdateOwner(existingSetting, newPkg)) {
synchronized (mQueriesViaPackageLock) {
mQueriesViaPackage.add(existingSetting.getAppId(),
newPkgSetting.getAppId());
@@ -697,7 +699,8 @@
}
}
if (canQueryViaPackage(newPkg, existingPkg)
- || canQueryAsInstaller(newPkgSetting, existingPkg)) {
+ || canQueryAsInstaller(newPkgSetting, existingPkg)
+ || canQueryAsUpdateOwner(newPkgSetting, existingPkg)) {
synchronized (mQueriesViaPackageLock) {
mQueriesViaPackage.add(newPkgSetting.getAppId(),
existingSetting.getAppId());
diff --git a/services/core/java/com/android/server/pm/AppsFilterUtils.java b/services/core/java/com/android/server/pm/AppsFilterUtils.java
index 8da1d21..d38b83f 100644
--- a/services/core/java/com/android/server/pm/AppsFilterUtils.java
+++ b/services/core/java/com/android/server/pm/AppsFilterUtils.java
@@ -91,6 +91,15 @@
return false;
}
+ public static boolean canQueryAsUpdateOwner(PackageStateInternal querying,
+ AndroidPackage potentialTarget) {
+ final InstallSource installSource = querying.getInstallSource();
+ if (potentialTarget.getPackageName().equals(installSource.mUpdateOwnerPackageName)) {
+ return true;
+ }
+ return false;
+ }
+
public static boolean canQueryViaUsesLibrary(AndroidPackage querying,
AndroidPackage potentialTarget) {
if (potentialTarget.getLibraryNames().isEmpty()) {
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index 9785d47..5c4c7c9 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -189,13 +189,14 @@
void onPackagesUpdated(ArraySet<String> updatedPackages);
}
- public BackgroundDexOptService(
- Context context, DexManager dexManager, PackageManagerService pm) {
+ public BackgroundDexOptService(Context context, DexManager dexManager, PackageManagerService pm)
+ throws LegacyDexoptDisabledException {
this(new Injector(context, dexManager, pm));
}
@VisibleForTesting
- public BackgroundDexOptService(Injector injector) {
+ public BackgroundDexOptService(Injector injector) throws LegacyDexoptDisabledException {
+ Installer.checkLegacyDexoptDisabled();
mInjector = injector;
mDexOptHelper = mInjector.getDexOptHelper();
LocalServices.addService(BackgroundDexOptService.class, this);
@@ -405,11 +406,15 @@
new TimingsTraceAndSlog(TAG, Trace.TRACE_TAG_PACKAGE_MANAGER);
tr.traceBegin("jobExecution");
boolean completed = false;
+ boolean fatalError = false;
try {
completed = runIdleOptimization(
pm, pkgs, params.getJobId() == JOB_POST_BOOT_UPDATE);
} catch (LegacyDexoptDisabledException e) {
Slog.wtf(TAG, e);
+ } catch (RuntimeException e) {
+ fatalError = true;
+ throw e;
} finally { // Those cleanup should be done always.
tr.traceEnd();
Slog.i(TAG,
@@ -422,12 +427,10 @@
if (completed) {
markPostBootUpdateCompleted(params);
}
- // Reschedule when cancelled
- job.jobFinished(params, !completed);
- } else {
- // Periodic job
- job.jobFinished(params, false /* reschedule */);
}
+ // Reschedule when cancelled. No need to reschedule when failed with
+ // fatal error because it's likely to fail again.
+ job.jobFinished(params, !completed && !fatalError);
markDexOptCompleted();
}
}));
diff --git a/services/core/java/com/android/server/pm/BackgroundInstallControlService.java b/services/core/java/com/android/server/pm/BackgroundInstallControlService.java
index db3a343..69436da 100644
--- a/services/core/java/com/android/server/pm/BackgroundInstallControlService.java
+++ b/services/core/java/com/android/server/pm/BackgroundInstallControlService.java
@@ -22,6 +22,7 @@
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.IBackgroundInstallControlService;
+import android.content.pm.InstallSourceInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
@@ -183,10 +184,12 @@
return;
}
- String installerPackageName = null;
+ String installerPackageName;
+ String initiatingPackageName;
try {
- installerPackageName = mPackageManager
- .getInstallSourceInfo(packageName).getInstallingPackageName();
+ final InstallSourceInfo installInfo = mPackageManager.getInstallSourceInfo(packageName);
+ installerPackageName = installInfo.getInstallingPackageName();
+ initiatingPackageName = installInfo.getInitiatingPackageName();
} catch (PackageManager.NameNotFoundException e) {
Slog.w(TAG, "Package's installer not found " + packageName);
return;
@@ -196,7 +199,8 @@
final long installTimestamp = System.currentTimeMillis()
- (SystemClock.uptimeMillis() - appInfo.createTimestamp);
- if (wasForegroundInstallation(installerPackageName, userId, installTimestamp)) {
+ if (installedByAdb(initiatingPackageName)
+ || wasForegroundInstallation(installerPackageName, userId, installTimestamp)) {
return;
}
@@ -205,6 +209,12 @@
writeBackgroundInstalledPackagesToDisk();
}
+ // ADB sets installerPackageName to null, this creates a loophole to bypass BIC which will be
+ // addressed with b/265203007
+ private boolean installedByAdb(String initiatingPackageName) {
+ return initiatingPackageName == null;
+ }
+
private boolean wasForegroundInstallation(String installerPackageName,
int userId, long installTimestamp) {
TreeSet<BackgroundInstallControlService.ForegroundTimeFrame> foregroundTimeFrames =
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
index c6700e6..2752104 100644
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
@@ -1755,6 +1755,7 @@
forwardingResolveInfo.isDefault = true;
forwardingResolveInfo.filter = new IntentFilter(filter.getIntentFilter());
forwardingResolveInfo.targetUserId = targetUserId;
+ forwardingResolveInfo.userHandle = UserHandle.of(sourceUserId);
return forwardingResolveInfo;
}
diff --git a/services/core/java/com/android/server/pm/CrossProfileIntentFilterHelper.java b/services/core/java/com/android/server/pm/CrossProfileIntentFilterHelper.java
index e682586..51214fa 100644
--- a/services/core/java/com/android/server/pm/CrossProfileIntentFilterHelper.java
+++ b/services/core/java/com/android/server/pm/CrossProfileIntentFilterHelper.java
@@ -54,7 +54,8 @@
UserProperties currentUserProperties = mUserManagerInternal
.getUserProperties(userInfo.id);
- if (currentUserProperties.getUpdateCrossProfileIntentFiltersOnOTA()) {
+ if (currentUserProperties != null
+ && currentUserProperties.getUpdateCrossProfileIntentFiltersOnOTA()) {
int parentUserId = mUserManagerInternal.getProfileParentId(userInfo.id);
if (parentUserId != userInfo.id) {
clearCrossProfileIntentFilters(userInfo.id,
diff --git a/services/core/java/com/android/server/pm/DexOptHelper.java b/services/core/java/com/android/server/pm/DexOptHelper.java
index 8757310..53e23e0 100644
--- a/services/core/java/com/android/server/pm/DexOptHelper.java
+++ b/services/core/java/com/android/server/pm/DexOptHelper.java
@@ -41,6 +41,7 @@
import android.annotation.RequiresPermission;
import android.app.ActivityManager;
import android.app.AppGlobals;
+import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.content.pm.SharedLibraryInfo;
@@ -64,8 +65,8 @@
import com.android.server.art.ArtManagerLocal;
import com.android.server.art.DexUseManagerLocal;
import com.android.server.art.model.ArtFlags;
-import com.android.server.art.model.OptimizeParams;
-import com.android.server.art.model.OptimizeResult;
+import com.android.server.art.model.DexoptParams;
+import com.android.server.art.model.DexoptResult;
import com.android.server.pm.Installer.InstallerException;
import com.android.server.pm.Installer.LegacyDexoptDisabledException;
import com.android.server.pm.PackageDexOptimizer.DexOptResult;
@@ -84,8 +85,10 @@
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
+import java.util.Objects;
import java.util.Optional;
import java.util.Set;
+import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
@@ -416,17 +419,22 @@
return true;
}
+ @DexOptResult int dexoptStatus;
if (options.isDexoptOnlySecondaryDex()) {
- // TODO(b/251903639): Call into ART Service.
- try {
- return mPm.getDexManager().dexoptSecondaryDex(options);
- } catch (LegacyDexoptDisabledException e) {
- throw new RuntimeException(e);
+ Optional<Integer> artSrvRes = performDexOptWithArtService(options, 0 /* extraFlags */);
+ if (artSrvRes.isPresent()) {
+ dexoptStatus = artSrvRes.get();
+ } else {
+ try {
+ return mPm.getDexManager().dexoptSecondaryDex(options);
+ } catch (LegacyDexoptDisabledException e) {
+ throw new RuntimeException(e);
+ }
}
} else {
- int dexoptStatus = performDexOptWithStatus(options);
- return dexoptStatus != PackageDexOptimizer.DEX_OPT_FAILED;
+ dexoptStatus = performDexOptWithStatus(options);
}
+ return dexoptStatus != PackageDexOptimizer.DEX_OPT_FAILED;
}
/**
@@ -455,7 +463,8 @@
// if the package can now be considered up to date for the given filter.
@DexOptResult
private int performDexOptInternal(DexoptOptions options) {
- Optional<Integer> artSrvRes = performDexOptWithArtService(options);
+ Optional<Integer> artSrvRes =
+ performDexOptWithArtService(options, ArtFlags.FLAG_SHOULD_INCLUDE_DEPENDENCIES);
if (artSrvRes.isPresent()) {
return artSrvRes.get();
}
@@ -492,7 +501,8 @@
* @return a {@link DexOptResult}, or empty if the request isn't supported so that it is
* necessary to fall back to the legacy code paths.
*/
- private Optional<Integer> performDexOptWithArtService(DexoptOptions options) {
+ private Optional<Integer> performDexOptWithArtService(DexoptOptions options,
+ /*@DexoptFlags*/ int extraFlags) {
ArtManagerLocal artManager = getArtManagerLocal();
if (artManager == null) {
return Optional.empty();
@@ -512,41 +522,19 @@
return Optional.of(PackageDexOptimizer.DEX_OPT_SKIPPED);
}
- // TODO(b/245301593): Delete the conditional when ART Service supports
- // FLAG_SHOULD_INCLUDE_DEPENDENCIES and we can just set it unconditionally.
- /*@OptimizeFlags*/ int extraFlags = ops.getUsesLibraries().isEmpty()
- ? 0
- : ArtFlags.FLAG_SHOULD_INCLUDE_DEPENDENCIES;
-
- OptimizeParams params = options.convertToOptimizeParams(extraFlags);
+ DexoptParams params = options.convertToDexoptParams(extraFlags);
if (params == null) {
return Optional.empty();
}
- // TODO(b/251903639): Either remove controlDexOptBlocking, or don't ignore it here.
- OptimizeResult result;
+ DexoptResult result;
try {
- result = artManager.optimizePackage(snapshot, options.getPackageName(), params);
+ result = artManager.dexoptPackage(snapshot, options.getPackageName(), params);
} catch (UnsupportedOperationException e) {
reportArtManagerFallback(options.getPackageName(), e.toString());
return Optional.empty();
}
- // TODO(b/251903639): Move this to ArtManagerLocal.addOptimizePackageDoneCallback when
- // it is implemented.
- for (OptimizeResult.PackageOptimizeResult pkgRes : result.getPackageOptimizeResults()) {
- PackageState ps = snapshot.getPackageState(pkgRes.getPackageName());
- AndroidPackage ap = ps != null ? ps.getAndroidPackage() : null;
- if (ap != null) {
- CompilerStats.PackageStats stats = mPm.getOrCreateCompilerPackageStats(ap);
- for (OptimizeResult.DexContainerFileOptimizeResult dexRes :
- pkgRes.getDexContainerFileOptimizeResults()) {
- stats.setCompileTime(
- dexRes.getDexContainerFile(), dexRes.getDex2oatWallTimeMillis());
- }
- }
- }
-
return Optional.of(convertToDexOptResult(result));
}
}
@@ -628,7 +616,8 @@
// performDexOptWithArtService ignores the snapshot and takes its own, so it can race with
// the package checks above, but at worst the effect is only a bit less friendly error
// below.
- Optional<Integer> artSrvRes = performDexOptWithArtService(options);
+ Optional<Integer> artSrvRes =
+ performDexOptWithArtService(options, ArtFlags.FLAG_SHOULD_INCLUDE_DEPENDENCIES);
int res;
if (artSrvRes.isPresent()) {
res = artSrvRes.get();
@@ -965,8 +954,54 @@
}
}
+ private static class DexoptDoneHandler implements ArtManagerLocal.DexoptDoneCallback {
+ @NonNull private final PackageManagerService mPm;
+
+ DexoptDoneHandler(@NonNull PackageManagerService pm) { mPm = pm; }
+
+ /**
+ * Called after every package dexopt operation done by {@link ArtManagerLocal}.
+ */
+ @Override
+ public void onDexoptDone(@NonNull DexoptResult result) {
+ for (DexoptResult.PackageDexoptResult pkgRes : result.getPackageDexoptResults()) {
+ CompilerStats.PackageStats stats =
+ mPm.getOrCreateCompilerPackageStats(pkgRes.getPackageName());
+ for (DexoptResult.DexContainerFileDexoptResult dexRes :
+ pkgRes.getDexContainerFileDexoptResults()) {
+ stats.setCompileTime(
+ dexRes.getDexContainerFile(), dexRes.getDex2oatWallTimeMillis());
+ }
+ }
+
+ synchronized (mPm.mLock) {
+ mPm.getPackageUsage().maybeWriteAsync(mPm.mSettings.getPackagesLocked());
+ mPm.mCompilerStats.maybeWriteAsync();
+ }
+ }
+ }
+
/**
- * Returns {@link ArtManagerLocal} if ART Service should be used for package optimization.
+ * Initializes {@link ArtManagerLocal} before {@link getArtManagerLocal} is called.
+ */
+ public static void initializeArtManagerLocal(
+ @NonNull Context systemContext, @NonNull PackageManagerService pm) {
+ if (!useArtService()) {
+ return;
+ }
+
+ ArtManagerLocal artManager = new ArtManagerLocal(systemContext);
+ // There doesn't appear to be any checks that @NonNull is heeded, so use requireNonNull
+ // below to ensure we don't store away a null that we'll fail on later.
+ artManager.addDexoptDoneCallback(false /* onlyIncludeUpdates */,
+ Runnable::run, new DexoptDoneHandler(Objects.requireNonNull(pm)));
+ LocalManagerRegistry.addManager(ArtManagerLocal.class, artManager);
+
+ artManager.scheduleBackgroundDexoptJob();
+ }
+
+ /**
+ * Returns {@link ArtManagerLocal} if ART Service should be used for package dexopt.
*/
private static @Nullable ArtManagerLocal getArtManagerLocal() {
if (!useArtService()) {
@@ -980,25 +1015,25 @@
}
/**
- * Converts an ART Service {@link OptimizeResult} to {@link DexOptResult}.
+ * Converts an ART Service {@link DexoptResult} to {@link DexOptResult}.
*
* For interfacing {@link ArtManagerLocal} with legacy dex optimization code in PackageManager.
*/
@DexOptResult
- private static int convertToDexOptResult(OptimizeResult result) {
- /*@OptimizeStatus*/ int status = result.getFinalStatus();
+ private static int convertToDexOptResult(DexoptResult result) {
+ /*@DexoptResultStatus*/ int status = result.getFinalStatus();
switch (status) {
- case OptimizeResult.OPTIMIZE_SKIPPED:
+ case DexoptResult.DEXOPT_SKIPPED:
return PackageDexOptimizer.DEX_OPT_SKIPPED;
- case OptimizeResult.OPTIMIZE_FAILED:
+ case DexoptResult.DEXOPT_FAILED:
return PackageDexOptimizer.DEX_OPT_FAILED;
- case OptimizeResult.OPTIMIZE_PERFORMED:
+ case DexoptResult.DEXOPT_PERFORMED:
return PackageDexOptimizer.DEX_OPT_PERFORMED;
- case OptimizeResult.OPTIMIZE_CANCELLED:
+ case DexoptResult.DEXOPT_CANCELLED:
return PackageDexOptimizer.DEX_OPT_CANCELLED;
default:
- throw new IllegalArgumentException("OptimizeResult for "
- + result.getPackageOptimizeResults().get(0).getPackageName()
+ throw new IllegalArgumentException("DexoptResult for "
+ + result.getPackageDexoptResults().get(0).getPackageName()
+ " has unsupported status " + status);
}
}
diff --git a/services/core/java/com/android/server/pm/DumpHelper.java b/services/core/java/com/android/server/pm/DumpHelper.java
index 3385a09..fcaaa90 100644
--- a/services/core/java/com/android/server/pm/DumpHelper.java
+++ b/services/core/java/com/android/server/pm/DumpHelper.java
@@ -111,6 +111,8 @@
dumpState.setOptionEnabled(DumpState.OPTION_DUMP_ALL_COMPONENTS);
} else if ("-f".equals(opt)) {
dumpState.setOptionEnabled(DumpState.OPTION_SHOW_FILTERS);
+ } else if ("--include-apex".equals(opt)) {
+ dumpState.setOptionEnabled(DumpState.OPTION_INCLUDE_APEX);
} else if ("--proto".equals(opt)) {
dumpProto(snapshot, fd);
return;
diff --git a/services/core/java/com/android/server/pm/DumpState.java b/services/core/java/com/android/server/pm/DumpState.java
index 6225753..0bdce21 100644
--- a/services/core/java/com/android/server/pm/DumpState.java
+++ b/services/core/java/com/android/server/pm/DumpState.java
@@ -51,6 +51,7 @@
public static final int OPTION_SHOW_FILTERS = 1 << 0;
public static final int OPTION_DUMP_ALL_COMPONENTS = 1 << 1;
public static final int OPTION_SKIP_PERMISSIONS = 1 << 2;
+ public static final int OPTION_INCLUDE_APEX = 1 << 3;
private int mTypes;
diff --git a/services/core/java/com/android/server/pm/InitAppsHelper.java b/services/core/java/com/android/server/pm/InitAppsHelper.java
index 6825dd7..5c4447e 100644
--- a/services/core/java/com/android/server/pm/InitAppsHelper.java
+++ b/services/core/java/com/android/server/pm/InitAppsHelper.java
@@ -21,11 +21,9 @@
import static com.android.internal.util.FrameworkStatsLog.BOOT_TIME_EVENT_DURATION__EVENT__OTA_PACKAGE_MANAGER_DATA_APP_AVG_SCAN_TIME;
import static com.android.internal.util.FrameworkStatsLog.BOOT_TIME_EVENT_DURATION__EVENT__OTA_PACKAGE_MANAGER_SYSTEM_APP_AVG_SCAN_TIME;
import static com.android.server.pm.PackageManagerService.SCAN_AS_APK_IN_APEX;
-import static com.android.server.pm.PackageManagerService.SCAN_AS_FACTORY;
import static com.android.server.pm.PackageManagerService.SCAN_AS_PRIVILEGED;
import static com.android.server.pm.PackageManagerService.SCAN_AS_SYSTEM;
import static com.android.server.pm.PackageManagerService.SCAN_BOOTING;
-import static com.android.server.pm.PackageManagerService.SCAN_DROP_CACHE;
import static com.android.server.pm.PackageManagerService.SCAN_FIRST_BOOT_OR_UPGRADE;
import static com.android.server.pm.PackageManagerService.SCAN_INITIAL;
import static com.android.server.pm.PackageManagerService.SCAN_NO_DEX;
@@ -147,14 +145,7 @@
sp.getFolder().getAbsolutePath())
|| apexInfo.preInstalledApexPath.getAbsolutePath().startsWith(
sp.getFolder().getAbsolutePath() + File.separator)) {
- int additionalScanFlag = SCAN_AS_APK_IN_APEX;
- if (apexInfo.isFactory) {
- additionalScanFlag |= SCAN_AS_FACTORY;
- }
- if (apexInfo.activeApexChanged) {
- additionalScanFlag |= SCAN_DROP_CACHE;
- }
- return new ScanPartition(apexInfo.apexDirectory, sp, additionalScanFlag);
+ return new ScanPartition(apexInfo.apexDirectory, sp, apexInfo);
}
}
return null;
@@ -266,7 +257,7 @@
}
scanDirTracedLI(mPm.getAppInstallDir(), 0,
- mScanFlags | SCAN_REQUIRE_KNOWN, packageParser, mExecutorService);
+ mScanFlags | SCAN_REQUIRE_KNOWN, packageParser, mExecutorService, null);
List<Runnable> unfinishedTasks = mExecutorService.shutdownNow();
if (!unfinishedTasks.isEmpty()) {
@@ -335,12 +326,12 @@
}
scanDirTracedLI(partition.getOverlayFolder(),
mSystemParseFlags, mSystemScanFlags | partition.scanFlag,
- packageParser, executorService);
+ packageParser, executorService, partition.apexInfo);
}
scanDirTracedLI(frameworkDir,
mSystemParseFlags, mSystemScanFlags | SCAN_NO_DEX | SCAN_AS_PRIVILEGED,
- packageParser, executorService);
+ packageParser, executorService, null);
if (!mPm.mPackages.containsKey("android")) {
throw new IllegalStateException(
"Failed to load frameworks package; check log for warnings");
@@ -352,11 +343,11 @@
scanDirTracedLI(partition.getPrivAppFolder(),
mSystemParseFlags,
mSystemScanFlags | SCAN_AS_PRIVILEGED | partition.scanFlag,
- packageParser, executorService);
+ packageParser, executorService, partition.apexInfo);
}
scanDirTracedLI(partition.getAppFolder(),
mSystemParseFlags, mSystemScanFlags | partition.scanFlag,
- packageParser, executorService);
+ packageParser, executorService, partition.apexInfo);
}
}
@@ -373,7 +364,8 @@
@GuardedBy({"mPm.mInstallLock", "mPm.mLock"})
private void scanDirTracedLI(File scanDir, int parseFlags, int scanFlags,
- PackageParser2 packageParser, ExecutorService executorService) {
+ PackageParser2 packageParser, ExecutorService executorService,
+ @Nullable ApexManager.ActiveApexInfo apexInfo) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanDir [" + scanDir.getAbsolutePath() + "]");
try {
if ((scanFlags & SCAN_AS_APK_IN_APEX) != 0) {
@@ -381,7 +373,7 @@
parseFlags |= PARSE_APK_IN_APEX;
}
mInstallPackageHelper.installPackagesFromDir(scanDir, parseFlags,
- scanFlags, packageParser, executorService);
+ scanFlags, packageParser, executorService, apexInfo);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
diff --git a/services/core/java/com/android/server/pm/InstallArgs.java b/services/core/java/com/android/server/pm/InstallArgs.java
index ced547c..9cf9122 100644
--- a/services/core/java/com/android/server/pm/InstallArgs.java
+++ b/services/core/java/com/android/server/pm/InstallArgs.java
@@ -59,7 +59,7 @@
final boolean mForceQueryableOverride;
final int mDataLoaderType;
final int mPackageSource;
- final boolean mKeepApplicationEnabledSetting;
+ final boolean mApplicationEnabledSettingPersistent;
// The list of instruction sets supported by this app. This is currently
// only used during the rmdex() phase to clean up resources. We can get rid of this
@@ -74,7 +74,7 @@
int autoRevokePermissionsMode, String traceMethod, int traceCookie,
SigningDetails signingDetails, int installReason, int installScenario,
boolean forceQueryableOverride, int dataLoaderType, int packageSource,
- boolean keepApplicationEnabledSetting) {
+ boolean applicationEnabledSettingPersistent) {
mOriginInfo = originInfo;
mMoveInfo = moveInfo;
mInstallFlags = installFlags;
@@ -95,7 +95,7 @@
mForceQueryableOverride = forceQueryableOverride;
mDataLoaderType = dataLoaderType;
mPackageSource = packageSource;
- mKeepApplicationEnabledSetting = keepApplicationEnabledSetting;
+ mApplicationEnabledSettingPersistent = applicationEnabledSettingPersistent;
}
/**
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 8711447..f0f23cd 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -333,6 +333,10 @@
if (updateOwnerFromSysconfig != null) {
// For system app, we always use the update owner from sysconfig if presented.
installSource = installSource.setUpdateOwnerPackageName(updateOwnerFromSysconfig);
+ } else if (!parsedPackage.isAllowUpdateOwnership()) {
+ // If the app wants to opt-out of the update ownership enforcement via manifest,
+ // it overrides the installer's use of #setRequestUpdateOwnership.
+ installSource = installSource.setUpdateOwnerPackageName(null);
} else if (!isApex) {
final boolean isUpdate = oldPkgSetting != null;
final String oldUpdateOwner =
@@ -363,10 +367,11 @@
if ((scanFlags & SCAN_AS_APK_IN_APEX) != 0) {
boolean isFactory = (scanFlags & SCAN_AS_FACTORY) != 0;
- pkgSetting.getPkgState().setApkInApex(true);
pkgSetting.getPkgState().setApkInUpdatedApex(!isFactory);
}
+ pkgSetting.getPkgState().setApexModuleName(request.getApexModuleName());
+
// TODO(toddke): Consider a method specifically for modifying the Package object
// post scan; or, moving this stuff out of the Package object since it has nothing
// to do with the package on disk.
@@ -1142,7 +1147,7 @@
if (onExternal) {
Slog.i(TAG, "Static shared libs can only be installed on internal storage.");
throw new PrepareFailure(INSTALL_FAILED_INVALID_INSTALL_LOCATION,
- "Packages declaring static-shared libs cannot be updated");
+ "Static shared libs can only be installed on internal storage.");
}
}
@@ -1712,6 +1717,7 @@
+ ", old=" + oldPackage);
}
request.setReturnCode(PackageManager.INSTALL_SUCCEEDED);
+ request.setApexModuleName(oldPackageState.getApexModuleName());
targetParseFlags = systemParseFlags;
targetScanFlags = systemScanFlags;
} else { // non system replace
@@ -2123,7 +2129,7 @@
}
// Enable system package for requested users
if (installedForUsers != null
- && !installRequest.isKeepApplicationEnabledSetting()) {
+ && !installRequest.isApplicationEnabledSettingPersistent()) {
for (int origUserId : installedForUsers) {
if (userId == UserHandle.USER_ALL || userId == origUserId) {
ps.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT,
@@ -2176,7 +2182,7 @@
// be installed and enabled. The caller, however, can explicitly specify to
// keep the existing enabled state.
ps.setInstalled(true, userId);
- if (!installRequest.isKeepApplicationEnabledSetting()) {
+ if (!installRequest.isApplicationEnabledSettingPersistent()) {
ps.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, userId,
installerPackageName);
}
@@ -2185,7 +2191,7 @@
// Thus, updating the settings to install the app for all users.
for (int currentUserId : allUsers) {
ps.setInstalled(true, currentUserId);
- if (!installRequest.isKeepApplicationEnabledSetting()) {
+ if (!installRequest.isApplicationEnabledSettingPersistent()) {
ps.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, currentUserId,
installerPackageName);
}
@@ -2287,7 +2293,7 @@
}
}
installRequest.setName(pkgName);
- installRequest.setUid(pkg.getUid());
+ installRequest.setAppId(pkg.getUid());
installRequest.setPkg(pkg);
installRequest.setReturnCode(PackageManager.INSTALL_SUCCEEDED);
//to update install status
@@ -2772,7 +2778,7 @@
}
Bundle extras = new Bundle();
- extras.putInt(Intent.EXTRA_UID, request.getUid());
+ extras.putInt(Intent.EXTRA_UID, request.getAppId());
if (update) {
extras.putBoolean(Intent.EXTRA_REPLACING, true);
}
@@ -2795,7 +2801,7 @@
// Send PACKAGE_ADDED broadcast for users that see the package for the first time
// sendPackageAddedForNewUsers also deals with system apps
- int appId = UserHandle.getAppId(request.getUid());
+ int appId = UserHandle.getAppId(request.getAppId());
boolean isSystem = request.isInstallSystem();
mPm.sendPackageAddedForNewUsers(mPm.snapshotComputer(), packageName,
isSystem || virtualPreload, virtualPreload /*startReceiver*/, appId,
@@ -2940,9 +2946,9 @@
}
if (allNewUsers && !update) {
- mPm.notifyPackageAdded(packageName, request.getUid());
+ mPm.notifyPackageAdded(packageName, request.getAppId());
} else {
- mPm.notifyPackageChanged(packageName, request.getUid());
+ mPm.notifyPackageChanged(packageName, request.getAppId());
}
// Log current value of "unknown sources" setting
@@ -3168,7 +3174,7 @@
final RemovePackageHelper removePackageHelper = new RemovePackageHelper(mPm);
removePackageHelper.removePackage(stubPkg, true /*chatty*/);
try {
- return scanSystemPackageTracedLI(scanFile, parseFlags, scanFlags);
+ return scanSystemPackageTracedLI(scanFile, parseFlags, scanFlags, null);
} catch (PackageManagerException e) {
Slog.w(TAG, "Failed to install compressed system package:" + stubPkg.getPackageName(),
e);
@@ -3300,7 +3306,7 @@
| ParsingPackageUtils.PARSE_IS_SYSTEM_DIR;
@PackageManagerService.ScanFlags int scanFlags = mPm.getSystemPackageScanFlags(codePath);
final AndroidPackage pkg = scanSystemPackageTracedLI(
- codePath, parseFlags, scanFlags);
+ codePath, parseFlags, scanFlags, null);
synchronized (mPm.mLock) {
PackageSetting pkgSetting = mPm.mSettings.getPackageLPr(pkg.getPackageName());
@@ -3480,7 +3486,7 @@
try {
final File codePath = new File(pkg.getPath());
synchronized (mPm.mInstallLock) {
- scanSystemPackageTracedLI(codePath, 0, scanFlags);
+ scanSystemPackageTracedLI(codePath, 0, scanFlags, null);
}
} catch (PackageManagerException e) {
Slog.e(TAG, "Failed to parse updated, ex-system package: "
@@ -3559,7 +3565,8 @@
if (throwable == null) {
try {
- addForInitLI(parseResult.parsedPackage, newParseFlags, newScanFlags, null);
+ addForInitLI(parseResult.parsedPackage, newParseFlags, newScanFlags, null,
+ new ApexManager.ActiveApexInfo(ai));
AndroidPackage pkg = parseResult.parsedPackage.hideAsFinal();
if (ai.isFactory && !ai.isActive) {
disableSystemPackageLPw(pkg);
@@ -3581,8 +3588,8 @@
@GuardedBy({"mPm.mInstallLock", "mPm.mLock"})
public void installPackagesFromDir(File scanDir, int parseFlags,
- int scanFlags, PackageParser2 packageParser,
- ExecutorService executorService) {
+ int scanFlags, PackageParser2 packageParser, ExecutorService executorService,
+ @Nullable ApexManager.ActiveApexInfo apexInfo) {
final File[] files = scanDir.listFiles();
if (ArrayUtils.isEmpty(files)) {
Log.d(TAG, "No files in app dir " + scanDir);
@@ -3630,7 +3637,7 @@
}
try {
addForInitLI(parseResult.parsedPackage, parseFlags, scanFlags,
- new UserHandle(UserHandle.USER_SYSTEM));
+ new UserHandle(UserHandle.USER_SYSTEM), apexInfo);
} catch (PackageManagerException e) {
errorCode = e.error;
errorMsg = "Failed to scan " + parseResult.scanFile + ": " + e.getMessage();
@@ -3693,7 +3700,7 @@
try {
synchronized (mPm.mInstallLock) {
final AndroidPackage newPkg = scanSystemPackageTracedLI(
- scanFile, reparseFlags, rescanFlags);
+ scanFile, reparseFlags, rescanFlags, null);
// We rescanned a stub, add it to the list of stubbed system packages
if (newPkg.isStub()) {
stubSystemApps.add(packageName);
@@ -3712,10 +3719,11 @@
*/
@GuardedBy("mPm.mInstallLock")
public AndroidPackage scanSystemPackageTracedLI(File scanFile, final int parseFlags,
- int scanFlags) throws PackageManagerException {
+ int scanFlags, @Nullable ApexManager.ActiveApexInfo apexInfo)
+ throws PackageManagerException {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanPackage [" + scanFile.toString() + "]");
try {
- return scanSystemPackageLI(scanFile, parseFlags, scanFlags);
+ return scanSystemPackageLI(scanFile, parseFlags, scanFlags, apexInfo);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
@@ -3726,7 +3734,8 @@
* Returns {@code null} in case of errors and the error code is stored in mLastScanError
*/
@GuardedBy("mPm.mInstallLock")
- private AndroidPackage scanSystemPackageLI(File scanFile, int parseFlags, int scanFlags)
+ private AndroidPackage scanSystemPackageLI(File scanFile, int parseFlags, int scanFlags,
+ @Nullable ApexManager.ActiveApexInfo apexInfo)
throws PackageManagerException {
if (DEBUG_INSTALL) Slog.d(TAG, "Parsing: " + scanFile);
@@ -3744,7 +3753,7 @@
}
return addForInitLI(parsedPackage, parseFlags, scanFlags,
- new UserHandle(UserHandle.USER_SYSTEM));
+ new UserHandle(UserHandle.USER_SYSTEM), apexInfo);
}
/**
@@ -3764,7 +3773,26 @@
private AndroidPackage addForInitLI(ParsedPackage parsedPackage,
@ParsingPackageUtils.ParseFlags int parseFlags,
@PackageManagerService.ScanFlags int scanFlags,
- @Nullable UserHandle user) throws PackageManagerException {
+ @Nullable UserHandle user, @Nullable ApexManager.ActiveApexInfo activeApexInfo)
+ throws PackageManagerException {
+ PackageSetting disabledPkgSetting;
+ synchronized (mPm.mLock) {
+ disabledPkgSetting =
+ mPm.mSettings.getDisabledSystemPkgLPr(parsedPackage.getPackageName());
+ if (activeApexInfo != null && disabledPkgSetting != null) {
+ // When a disabled system package is scanned, its final PackageSetting is actually
+ // skipped and not added to any data structures, instead relying on the disabled
+ // setting read from the persisted Settings XML file. This persistence does not
+ // include the APEX module name, so here, re-set it from the active APEX info.
+ //
+ // This also has the (beneficial) side effect where if a package disappears from an
+ // APEX, leaving only a /data copy, it will lose its apexModuleName.
+ //
+ // This must be done before scanSystemPackageLI as that will throw in the case of a
+ // system -> data package.
+ disabledPkgSetting.setApexModuleName(activeApexInfo.apexModuleName);
+ }
+ }
final Pair<ScanResult, Boolean> scanResultPair = scanSystemPackageLI(
parsedPackage, parseFlags, scanFlags, user);
@@ -3773,6 +3801,24 @@
final InstallRequest installRequest = new InstallRequest(
parsedPackage, parseFlags, scanFlags, user, scanResult);
+ String existingApexModuleName = null;
+ synchronized (mPm.mLock) {
+ var existingPkgSetting = mPm.mSettings.getPackageLPr(parsedPackage.getPackageName());
+ if (existingPkgSetting != null) {
+ existingApexModuleName = existingPkgSetting.getApexModuleName();
+ }
+ }
+
+ if (activeApexInfo != null) {
+ installRequest.setApexModuleName(activeApexInfo.apexModuleName);
+ } else {
+ if (disabledPkgSetting != null) {
+ installRequest.setApexModuleName(disabledPkgSetting.getApexModuleName());
+ } else if (existingApexModuleName != null) {
+ installRequest.setApexModuleName(existingApexModuleName);
+ }
+ }
+
synchronized (mPm.mLock) {
boolean appIdCreated = false;
try {
diff --git a/services/core/java/com/android/server/pm/InstallRequest.java b/services/core/java/com/android/server/pm/InstallRequest.java
index c6cdc4c..a9c5773 100644
--- a/services/core/java/com/android/server/pm/InstallRequest.java
+++ b/services/core/java/com/android/server/pm/InstallRequest.java
@@ -44,6 +44,7 @@
import com.android.server.pm.parsing.pkg.ParsedPackage;
import com.android.server.pm.pkg.AndroidPackage;
+import com.android.server.pm.pkg.PackageState;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
@@ -81,7 +82,7 @@
/** Package Installed Info */
@Nullable
private String mName;
- private int mUid = INVALID_UID;
+ private int mAppId = INVALID_UID;
// The set of users that originally had this package installed.
@Nullable
private int[] mOrigUsers;
@@ -107,6 +108,12 @@
@Nullable
private ApexInfo mApexInfo;
+ /**
+ * For tracking {@link PackageState#getApexModuleName()}.
+ */
+ @Nullable
+ private String mApexModuleName;
+
@Nullable
private ScanResult mScanResult;
@@ -129,7 +136,7 @@
params.mTraceMethod, params.mTraceCookie, params.mSigningDetails,
params.mInstallReason, params.mInstallScenario, params.mForceQueryableOverride,
params.mDataLoaderType, params.mPackageSource,
- params.mKeepApplicationEnabledSetting);
+ params.mApplicationEnabledSettingPersistent);
mPackageMetrics = new PackageMetrics(this);
mIsInstallInherit = params.mIsInherit;
mSessionId = params.mSessionId;
@@ -158,7 +165,7 @@
mUserId = user.getIdentifier();
} else {
// APEX
- mUserId = INVALID_UID;
+ mUserId = UserHandle.USER_SYSTEM;
}
mInstallArgs = null;
mParsedPackage = parsedPackage;
@@ -348,6 +355,11 @@
}
@Nullable
+ public String getApexModuleName() {
+ return mApexModuleName;
+ }
+
+ @Nullable
public String getSourceInstallerPackageName() {
return mInstallArgs.mInstallSource.mInstallerPackageName;
}
@@ -367,8 +379,8 @@
return mOrigUsers;
}
- public int getUid() {
- return mUid;
+ public int getAppId() {
+ return mAppId;
}
@Nullable
@@ -499,8 +511,8 @@
return mScanResult.mChangedAbiCodePath;
}
- public boolean isKeepApplicationEnabledSetting() {
- return mInstallArgs == null ? false : mInstallArgs.mKeepApplicationEnabledSetting;
+ public boolean isApplicationEnabledSettingPersistent() {
+ return mInstallArgs == null ? false : mInstallArgs.mApplicationEnabledSettingPersistent;
}
public boolean isForceQueryableOverride() {
@@ -644,12 +656,16 @@
mApexInfo = apexInfo;
}
+ public void setApexModuleName(@Nullable String apexModuleName) {
+ mApexModuleName = apexModuleName;
+ }
+
public void setPkg(AndroidPackage pkg) {
mPkg = pkg;
}
- public void setUid(int uid) {
- mUid = uid;
+ public void setAppId(int appId) {
+ mAppId = appId;
}
public void setNewUsers(int[] newUsers) {
@@ -773,10 +789,10 @@
}
}
- public void onInstallCompleted(int userId) {
+ public void onInstallCompleted() {
if (getReturnCode() == INSTALL_SUCCEEDED) {
if (mPackageMetrics != null) {
- mPackageMetrics.onInstallSucceed(userId);
+ mPackageMetrics.onInstallSucceed();
}
}
}
diff --git a/services/core/java/com/android/server/pm/InstallingSession.java b/services/core/java/com/android/server/pm/InstallingSession.java
index eb3b29c..7b759e3 100644
--- a/services/core/java/com/android/server/pm/InstallingSession.java
+++ b/services/core/java/com/android/server/pm/InstallingSession.java
@@ -97,7 +97,7 @@
final boolean mIsInherit;
final int mSessionId;
final int mRequireUserAction;
- final boolean mKeepApplicationEnabledSetting;
+ final boolean mApplicationEnabledSettingPersistent;
// For move install
InstallingSession(OriginInfo originInfo, MoveInfo moveInfo, IPackageInstallObserver2 observer,
@@ -130,7 +130,7 @@
mIsInherit = false;
mSessionId = -1;
mRequireUserAction = USER_ACTION_UNSPECIFIED;
- mKeepApplicationEnabledSetting = false;
+ mApplicationEnabledSettingPersistent = false;
}
InstallingSession(int sessionId, File stagedDir, IPackageInstallObserver2 observer,
@@ -164,7 +164,7 @@
mIsInherit = sessionParams.mode == MODE_INHERIT_EXISTING;
mSessionId = sessionId;
mRequireUserAction = sessionParams.requireUserAction;
- mKeepApplicationEnabledSetting = sessionParams.keepApplicationEnabledSetting;
+ mApplicationEnabledSettingPersistent = sessionParams.applicationEnabledSettingPersistent;
}
@Override
@@ -535,7 +535,7 @@
mInstallPackageHelper.installPackagesTraced(installRequests);
for (InstallRequest request : installRequests) {
- request.onInstallCompleted(mUser.getIdentifier());
+ request.onInstallCompleted();
doPostInstall(request);
}
}
@@ -609,6 +609,7 @@
// processApkInstallRequests() fails. Need a way to keep info stored in apexd
// and PMS in sync in the face of install failures.
request.setApexInfo(apexInfo);
+ request.setApexModuleName(apexInfo.moduleName);
mPm.mHandler.post(() -> processApkInstallRequests(true, requests));
return;
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 8ea7788..47e18f1 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -278,8 +278,8 @@
private static final String ATTR_SIGNATURE = "signature";
private static final String ATTR_CHECKSUM_KIND = "checksumKind";
private static final String ATTR_CHECKSUM_VALUE = "checksumValue";
- private static final String ATTR_KEEP_APPLICATION_ENABLED_SETTING =
- "keepApplicationEnabledSetting";
+ private static final String ATTR_APPLICATION_ENABLED_SETTING_PERSISTENT =
+ "applicationEnabledSettingPersistent";
private static final String PROPERTY_NAME_INHERIT_NATIVE = "pi.inherit_native_on_dont_kill";
private static final int[] EMPTY_CHILD_SESSION_ARRAY = EmptyArray.INT;
@@ -1163,7 +1163,7 @@
info.requireUserAction = params.requireUserAction;
info.installerUid = mInstallerUid;
info.packageSource = params.packageSource;
- info.keepApplicationEnabledSetting = params.keepApplicationEnabledSetting;
+ info.applicationEnabledSettingPersistent = params.applicationEnabledSettingPersistent;
info.pendingUserActionReason = userActionRequirementToReason(mUserActionRequirement);
}
return info;
@@ -1842,6 +1842,60 @@
dispatchSessionSealed();
}
+ @Override
+ public void seal() {
+ assertNotChild("seal");
+ assertCallerIsOwnerOrRoot();
+ try {
+ sealInternal();
+ for (var child : getChildSessions()) {
+ child.sealInternal();
+ }
+ } catch (PackageManagerException e) {
+ throw new IllegalStateException("Package is not valid", e);
+ }
+ }
+
+ private void sealInternal() throws PackageManagerException {
+ synchronized (mLock) {
+ sealLocked();
+ }
+ }
+
+ @Override
+ public List<String> fetchPackageNames() {
+ assertNotChild("fetchPackageNames");
+ assertCallerIsOwnerOrRoot();
+ var sessions = getSelfOrChildSessions();
+ var result = new ArrayList<String>(sessions.size());
+ for (var s : sessions) {
+ result.add(s.fetchPackageName());
+ }
+ return result;
+ }
+
+ private String fetchPackageName() {
+ assertSealed("fetchPackageName");
+ synchronized (mLock) {
+ final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing();
+ final List<File> addedFiles = getAddedApksLocked();
+ for (File addedFile : addedFiles) {
+ final ParseResult<ApkLite> result =
+ ApkLiteParseUtils.parseApkLite(input.reset(), addedFile, 0);
+ if (result.isError()) {
+ throw new IllegalStateException(
+ "Can't parse package for session=" + sessionId, result.getException());
+ }
+ final ApkLite apk = result.getResult();
+ var packageName = apk.getPackageName();
+ if (packageName != null) {
+ return packageName;
+ }
+ }
+ throw new IllegalStateException("Can't fetch package name for session=" + sessionId);
+ }
+ }
+
/**
* Kicks off the install flow. The first step is to persist 'sealed' flags
* to prevent mutations of hard links created later.
@@ -2095,6 +2149,11 @@
}
}
+ @NonNull
+ private List<PackageInstallerSession> getSelfOrChildSessions() {
+ return isMultiPackage() ? getChildSessions() : Collections.singletonList(this);
+ }
+
/**
* Seal the session to prevent further modification.
*
@@ -4494,8 +4553,8 @@
}
@Override
- public boolean isKeepApplicationEnabledSetting() {
- return params.keepApplicationEnabledSetting;
+ public boolean isApplicationEnabledSettingPersistent() {
+ return params.applicationEnabledSettingPersistent;
}
@Override
@@ -4886,8 +4945,8 @@
writeStringAttribute(out, ATTR_ABI_OVERRIDE, params.abiOverride);
writeStringAttribute(out, ATTR_VOLUME_UUID, params.volumeUuid);
out.attributeInt(null, ATTR_INSTALL_REASON, params.installReason);
- writeBooleanAttribute(out, ATTR_KEEP_APPLICATION_ENABLED_SETTING,
- params.keepApplicationEnabledSetting);
+ writeBooleanAttribute(out, ATTR_APPLICATION_ENABLED_SETTING_PERSISTENT,
+ params.applicationEnabledSettingPersistent);
final boolean isDataLoader = params.dataLoaderParams != null;
writeBooleanAttribute(out, ATTR_IS_DATALOADER, isDataLoader);
@@ -5051,8 +5110,8 @@
params.volumeUuid = readStringAttribute(in, ATTR_VOLUME_UUID);
params.installReason = in.getAttributeInt(null, ATTR_INSTALL_REASON);
params.packageSource = in.getAttributeInt(null, ATTR_PACKAGE_SOURCE);
- params.keepApplicationEnabledSetting = in.getAttributeBoolean(null,
- ATTR_KEEP_APPLICATION_ENABLED_SETTING, false);
+ params.applicationEnabledSettingPersistent = in.getAttributeBoolean(null,
+ ATTR_APPLICATION_ENABLED_SETTING_PERSISTENT, false);
if (in.getAttributeBoolean(null, ATTR_IS_DATALOADER, false)) {
params.dataLoaderParams = new DataLoaderParams(
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index d7cecff..dfd305a 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -716,7 +716,7 @@
* The list of all system partitions that may contain packages in ascending order of
* specificity (the more generic, the earlier in the list a partition appears).
*/
- @VisibleForTesting(visibility = Visibility.PRIVATE)
+ @VisibleForTesting(visibility = Visibility.PACKAGE)
public static final List<ScanPartition> SYSTEM_PARTITIONS = Collections.unmodifiableList(
PackagePartitions.getOrderedPartitions(ScanPartition::new));
@@ -789,8 +789,10 @@
final ArtManagerService mArtManagerService;
+ // TODO(b/260124949): Remove these.
final PackageDexOptimizer mPackageDexOptimizer;
- final BackgroundDexOptService mBackgroundDexOptService;
+ @Nullable
+ final BackgroundDexOptService mBackgroundDexOptService; // null when ART Service is in use.
// DexManager handles the usage of dex files (e.g. secondary files, whether or not a package
// is used by other apps).
private final DexManager mDexManager;
@@ -1567,7 +1569,16 @@
new DefaultSystemWrapper(),
LocalServices::getService,
context::getSystemService,
- (i, pm) -> new BackgroundDexOptService(i.getContext(), i.getDexManager(), pm),
+ (i, pm) -> {
+ if (useArtService()) {
+ return null;
+ }
+ try {
+ return new BackgroundDexOptService(i.getContext(), i.getDexManager(), pm);
+ } catch (LegacyDexoptDisabledException e) {
+ throw new RuntimeException(e);
+ }
+ },
(i, pm) -> IBackupManager.Stub.asInterface(ServiceManager.getService(
Context.BACKUP_SERVICE)),
(i, pm) -> new SharedLibrariesImpl(pm, i),
@@ -4287,11 +4298,14 @@
}
});
- // TODO(b/251903639): Call into ART Service.
- try {
- mBackgroundDexOptService.systemReady();
- } catch (LegacyDexoptDisabledException e) {
- throw new RuntimeException(e);
+ if (!useArtService()) {
+ // The background dexopt job is scheduled in DexOptHelper.initializeArtManagerLocal when
+ // ART Service is in use.
+ try {
+ mBackgroundDexOptService.systemReady();
+ } catch (LegacyDexoptDisabledException e) {
+ throw new RuntimeException(e);
+ }
}
// Prune unused static shared libraries which have been cached a period of time
@@ -6024,6 +6038,42 @@
}
@Override
+ public void relinquishUpdateOwnership(String targetPackage) {
+ final int callingUid = Binder.getCallingUid();
+ final int callingUserId = UserHandle.getUserId(callingUid);
+ final Computer snapshot = snapshotComputer();
+
+ final PackageStateInternal targetPackageState =
+ snapshot.getPackageStateForInstalledAndFiltered(targetPackage, callingUid,
+ callingUserId);
+ if (targetPackageState == null) {
+ throw new IllegalArgumentException("Unknown target package: " + targetPackage);
+ }
+
+ final String targetUpdateOwnerPackageName =
+ targetPackageState.getInstallSource().mUpdateOwnerPackageName;
+ final PackageStateInternal targetUpdateOwnerPkgSetting =
+ targetUpdateOwnerPackageName == null ? null
+ : snapshot.getPackageStateInternal(targetUpdateOwnerPackageName);
+
+ if (targetUpdateOwnerPkgSetting == null) {
+ return;
+ }
+
+ final int callingAppId = UserHandle.getAppId(callingUid);
+ final int targetUpdateOwnerAppId = targetUpdateOwnerPkgSetting.getAppId();
+ if (callingAppId != Process.SYSTEM_UID
+ && callingAppId != Process.SHELL_UID
+ && callingAppId != targetUpdateOwnerAppId) {
+ throw new SecurityException("Caller is not the current update owner.");
+ }
+
+ commitPackageStateMutation(null /* initialState */, targetPackage,
+ state -> state.setUpdateOwner(null /* updateOwnerPackageName */));
+ scheduleWriteSettings();
+ }
+
+ @Override
public boolean setInstantAppCookie(String packageName, byte[] cookie, int userId) {
if (HIDE_EPHEMERAL_APIS) {
return true;
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceInjector.java b/services/core/java/com/android/server/pm/PackageManagerServiceInjector.java
index eb033cb..13549f5 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceInjector.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceInjector.java
@@ -16,6 +16,7 @@
package com.android.server.pm;
+import android.annotation.Nullable;
import android.app.ActivityManagerInternal;
import android.app.backup.IBackupManager;
import android.content.ComponentName;
@@ -138,7 +139,8 @@
private final Singleton<DomainVerificationManagerInternal>
mDomainVerificationManagerInternalProducer;
private final Singleton<Handler> mHandlerProducer;
- private final Singleton<BackgroundDexOptService> mBackgroundDexOptService;
+ private final Singleton<BackgroundDexOptService>
+ mBackgroundDexOptService; // TODO(b/260124949): Remove this.
private final Singleton<IBackupManager> mIBackupManager;
private final Singleton<SharedLibrariesImpl> mSharedLibrariesProducer;
private final Singleton<CrossProfileIntentFilterHelper> mCrossProfileIntentFilterHelperProducer;
@@ -408,6 +410,7 @@
return getLocalService(ActivityManagerInternal.class);
}
+ @Nullable
public BackgroundDexOptService getBackgroundDexOptService() {
return mBackgroundDexOptService.get(this, mPackageManager);
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java b/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java
index 0c617ae..08ff51d 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java
@@ -106,7 +106,7 @@
public boolean isEngBuild;
public boolean isUserDebugBuild;
public int sdkInt = Build.VERSION.SDK_INT;
- public BackgroundDexOptService backgroundDexOptService;
+ public @Nullable BackgroundDexOptService backgroundDexOptService;
public final String incrementalVersion = Build.VERSION.INCREMENTAL;
public BroadcastHelper broadcastHelper;
public AppDataHelper appDataHelper;
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index a72ae56..0de1a4e 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -33,6 +33,7 @@
import static com.android.server.pm.PackageManagerService.STUB_SUFFIX;
import static com.android.server.pm.PackageManagerService.TAG;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
@@ -113,6 +114,8 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.nio.file.Path;
import java.security.SecureRandom;
import java.security.cert.CertificateEncodingException;
@@ -148,6 +151,29 @@
ThreadLocal.withInitial(() -> false);
/**
+ * Type used with {@link #canJoinSharedUserId(String, SigningDetails, SharedUserSetting, int)}
+ * when the package attempting to join the sharedUserId is a new install.
+ */
+ public static final int SHARED_USER_ID_JOIN_TYPE_INSTALL = 0;
+ /**
+ * Type used with {@link #canJoinSharedUserId(String, SigningDetails, SharedUserSetting, int)}
+ * when the package attempting to join the sharedUserId is an update.
+ */
+ public static final int SHARED_USER_ID_JOIN_TYPE_UPDATE = 1;
+ /**
+ * Type used with {@link #canJoinSharedUserId(String, SigningDetails, SharedUserSetting, int)}
+ * when the package attempting to join the sharedUserId is a part of the system image.
+ */
+ public static final int SHARED_USER_ID_JOIN_TYPE_SYSTEM = 2;
+ @IntDef(prefix = { "TYPE_" }, value = {
+ SHARED_USER_ID_JOIN_TYPE_INSTALL,
+ SHARED_USER_ID_JOIN_TYPE_UPDATE,
+ SHARED_USER_ID_JOIN_TYPE_SYSTEM,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SharedUserIdJoinType {}
+
+ /**
* Components of apps targeting Android T and above will stop receiving intents from
* external callers that do not match its declared intent filters.
*
@@ -575,17 +601,9 @@
// the older ones. We check to see if either the new package is signed by an older cert
// with which the current sharedUser is ok, or if it is signed by a newer one, and is ok
// with being sharedUser with the existing signing cert.
- boolean match = canJoinSharedUserId(parsedSignatures,
- sharedUserSetting.getSigningDetails());
- // Special case: if the sharedUserId capability check failed it could be due to this
- // being the only package in the sharedUserId so far and the lineage being updated to
- // deny the sharedUserId capability of the previous key in the lineage.
- final ArraySet<PackageStateInternal> susPackageStates =
- (ArraySet<PackageStateInternal>) sharedUserSetting.getPackageStates();
- if (!match && susPackageStates.size() == 1
- && susPackageStates.valueAt(0).getPackageName().equals(packageName)) {
- match = true;
- }
+ boolean match = canJoinSharedUserId(packageName, parsedSignatures, sharedUserSetting,
+ pkgSetting.getSigningDetails().getSignatures() != null
+ ? SHARED_USER_ID_JOIN_TYPE_UPDATE : SHARED_USER_ID_JOIN_TYPE_INSTALL);
if (!match && compareCompat) {
match = matchSignaturesCompat(
packageName, sharedUserSetting.signatures, parsedSignatures);
@@ -608,36 +626,6 @@
+ " has no signatures that match those in shared user "
+ sharedUserSetting.name + "; ignoring!");
}
- // It is possible that this package contains a lineage that blocks sharedUserId access
- // to an already installed package in the sharedUserId signed with a previous key.
- // Iterate over all of the packages in the sharedUserId and ensure any that are signed
- // with a key in this package's lineage have the SHARED_USER_ID capability granted.
- if (parsedSignatures.hasPastSigningCertificates()) {
- for (int i = 0; i < susPackageStates.size(); i++) {
- PackageStateInternal shUidPkgSetting = susPackageStates.valueAt(i);
- // if the current package in the sharedUserId is the package being updated then
- // skip this check as the update may revoke the sharedUserId capability from
- // the key with which this app was previously signed.
- if (packageName.equals(shUidPkgSetting.getPackageName())) {
- continue;
- }
- SigningDetails shUidSigningDetails =
- shUidPkgSetting.getSigningDetails();
- // The capability check only needs to be performed against the package if it is
- // signed with a key that is in the lineage of the package being installed.
- if (parsedSignatures.hasAncestor(shUidSigningDetails)) {
- if (!parsedSignatures.checkCapability(shUidSigningDetails,
- SigningDetails.CertCapabilities.SHARED_USER_ID)) {
- throw new PackageManagerException(
- INSTALL_FAILED_SHARED_USER_INCOMPATIBLE,
- "Package " + packageName
- + " revoked the sharedUserId capability from the"
- + " signing key used to sign "
- + shUidPkgSetting.getPackageName());
- }
- }
- }
- }
// If the lineage of this package diverges from the lineage of the sharedUserId then
// do not allow the installation to proceed.
if (!parsedSignatures.hasCommonAncestor(
@@ -651,25 +639,97 @@
}
/**
- * Returns whether the package with {@code packageSigningDetails} can join the sharedUserId
- * with {@code sharedUserSigningDetails}.
+ * Returns whether the package {@code packageName} can join the sharedUserId based on the
+ * settings in {@code sharedUserSetting}.
* <p>
* A sharedUserId maintains a shared {@link SigningDetails} containing the full lineage and
* capabilities for each package in the sharedUserId. A package can join the sharedUserId if
* its current signer is the same as the shared signer, or if the current signer of either
* is in the signing lineage of the other with the {@link
* SigningDetails.CertCapabilities#SHARED_USER_ID} capability granted to that previous signer
- * in the lineage.
+ * in the lineage. In the case of a key compromise, an app signed with a lineage revoking
+ * this capability from a previous signing key can still join the sharedUserId with another
+ * app signed with this previous key if the joining app is being updated; however, a new
+ * install will not be allowed until all apps have rotated off the key with the capability
+ * revoked.
*
+ * @param packageName the name of the package seeking to join the sharedUserId
* @param packageSigningDetails the {@code SigningDetails} of the package seeking to join the
- * sharedUserId
- * @param sharedUserSigningDetails the {@code SigningDetails} of the sharedUserId
+ * sharedUserId
+ * @param sharedUserSetting the {@code SharedUserSetting} for the sharedUserId {@code
+ * packageName} is seeking to join
+ * @param joinType the type of join (install, update, system, etc)
* @return true if the package seeking to join the sharedUserId meets the requirements
*/
- public static boolean canJoinSharedUserId(@NonNull SigningDetails packageSigningDetails,
- @NonNull SigningDetails sharedUserSigningDetails) {
- return packageSigningDetails.checkCapability(sharedUserSigningDetails, SHARED_USER_ID)
- || sharedUserSigningDetails.checkCapability(packageSigningDetails, SHARED_USER_ID);
+ public static boolean canJoinSharedUserId(@NonNull String packageName,
+ @NonNull SigningDetails packageSigningDetails,
+ @NonNull SharedUserSetting sharedUserSetting, @SharedUserIdJoinType int joinType) {
+ SigningDetails sharedUserSigningDetails = sharedUserSetting.getSigningDetails();
+ boolean capabilityGranted =
+ packageSigningDetails.checkCapability(sharedUserSigningDetails, SHARED_USER_ID)
+ || sharedUserSigningDetails.checkCapability(packageSigningDetails,
+ SHARED_USER_ID);
+
+ // If the current signer for either the package or the sharedUserId is the current signer
+ // of the other or in the lineage of the other with the SHARED_USER_ID capability granted,
+ // then a system and update join type can proceed; an install join type is not allowed here
+ // since the sharedUserId may contain packages that are signed with a key untrusted by
+ // the new package.
+ if (capabilityGranted && joinType != SHARED_USER_ID_JOIN_TYPE_INSTALL) {
+ return true;
+ }
+
+ // If the package is signed with a key that is no longer trusted by the sharedUserId, then
+ // the join should not be allowed unless this is a system join type; system packages can
+ // join the sharedUserId as long as they share a common lineage.
+ if (!capabilityGranted && sharedUserSigningDetails.hasAncestor(packageSigningDetails)) {
+ if (joinType == SHARED_USER_ID_JOIN_TYPE_SYSTEM) {
+ return true;
+ }
+ return false;
+ }
+
+ // If the package is signed with a rotated key that no longer trusts the sharedUserId key,
+ // then allow system and update join types to rotate away from an untrusted key; install
+ // join types are not allowed since a new package that doesn't trust a previous key
+ // shouldn't be allowed to join until all packages in the sharedUserId have rotated off the
+ // untrusted key.
+ if (!capabilityGranted && packageSigningDetails.hasAncestor(sharedUserSigningDetails)) {
+ if (joinType != SHARED_USER_ID_JOIN_TYPE_INSTALL) {
+ return true;
+ }
+ return false;
+ }
+
+ // If the capability is not granted and the package signatures are not an ancestor
+ // or descendant of the sharedUserId signatures, then do not allow any join type to join
+ // the sharedUserId since there are no common signatures.
+ if (!capabilityGranted) {
+ return false;
+ }
+
+ // At this point this is a new install with the capability granted; ensure the current
+ // packages in the sharedUserId are all signed by a key trusted by the new package.
+ final ArraySet<PackageStateInternal> susPackageStates =
+ (ArraySet<PackageStateInternal>) sharedUserSetting.getPackageStates();
+ if (packageSigningDetails.hasPastSigningCertificates()) {
+ for (PackageStateInternal shUidPkgSetting : susPackageStates) {
+ SigningDetails shUidSigningDetails = shUidPkgSetting.getSigningDetails();
+ // The capability check only needs to be performed against the package if it is
+ // signed with a key that is in the lineage of the package being installed.
+ if (packageSigningDetails.hasAncestor(shUidSigningDetails)) {
+ if (!packageSigningDetails.checkCapability(shUidSigningDetails,
+ SigningDetails.CertCapabilities.SHARED_USER_ID)) {
+ Slog.d(TAG, "Package " + packageName
+ + " revoked the sharedUserId capability from the"
+ + " signing key used to sign "
+ + shUidPkgSetting.getPackageName());
+ return false;
+ }
+ }
+ }
+ }
+ return true;
}
/**
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 849cbeb..0685435 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -2875,6 +2875,8 @@
newUserType = UserManager.USER_TYPE_FULL_DEMO;
} else if ("--ephemeral".equals(opt)) {
flags |= UserInfo.FLAG_EPHEMERAL;
+ } else if ("--for-testing".equals(opt)) {
+ flags |= UserInfo.FLAG_FOR_TESTING;
} else if ("--pre-create-only".equals(opt)) {
preCreateOnly = true;
} else if ("--user-type".equals(opt)) {
@@ -3291,7 +3293,7 @@
sessionParams.installFlags |= PackageManager.INSTALL_DISABLE_VERIFICATION;
break;
case "--skip-enable":
- sessionParams.setKeepApplicationEnabledSetting();
+ sessionParams.setApplicationEnabledSettingPersistent();
break;
case "--bypass-low-target-sdk-block":
sessionParams.installFlags |=
@@ -4269,8 +4271,8 @@
pw.println(" list users");
pw.println(" Lists the current users.");
pw.println("");
- pw.println(" create-user [--profileOf USER_ID] [--managed] [--restricted] [--ephemeral]");
- pw.println(" [--guest] [--pre-create-only] [--user-type USER_TYPE] USER_NAME");
+ pw.println(" create-user [--profileOf USER_ID] [--managed] [--restricted] [--guest]");
+ pw.println(" [--user-type USER_TYPE] [--ephemeral] [--for-testing] [--pre-create-only] USER_NAME");
pw.println(" Create a new user with the given USER_NAME, printing the new user identifier");
pw.println(" of the user.");
// TODO(b/142482943): Consider fetching the list of user types from UMS.
diff --git a/services/core/java/com/android/server/pm/PackageMetrics.java b/services/core/java/com/android/server/pm/PackageMetrics.java
index 8252a9fa..d4c1256 100644
--- a/services/core/java/com/android/server/pm/PackageMetrics.java
+++ b/services/core/java/com/android/server/pm/PackageMetrics.java
@@ -19,9 +19,11 @@
import static android.os.Process.INVALID_UID;
import android.annotation.IntDef;
+import android.app.ActivityManager;
import android.app.admin.SecurityLog;
import android.content.pm.PackageManager;
import android.content.pm.parsing.ApkLiteParseUtils;
+import android.os.UserHandle;
import android.util.Pair;
import android.util.SparseArray;
@@ -68,8 +70,8 @@
mInstallRequest = installRequest;
}
- public void onInstallSucceed(int userId) {
- reportInstallationToSecurityLog(userId);
+ public void onInstallSucceed() {
+ reportInstallationToSecurityLog(mInstallRequest.getUserId());
reportInstallationStats(true /* success */);
}
@@ -110,10 +112,11 @@
}
}
+
FrameworkStatsLog.write(FrameworkStatsLog.PACKAGE_INSTALLATION_SESSION_REPORTED,
mInstallRequest.getSessionId() /* session_id */,
packageName /* package_name */,
- mInstallRequest.getUid() /* uid */,
+ getUid(mInstallRequest.getAppId(), mInstallRequest.getUserId()) /* uid */,
newUsers /* user_ids */,
userManagerInternal.getUserTypesForStatsd(newUsers) /* user_types */,
originalUsers /* original_user_ids */,
@@ -140,6 +143,13 @@
);
}
+ private static int getUid(int appId, int userId) {
+ if (userId == UserHandle.USER_ALL) {
+ userId = ActivityManager.getCurrentUser();
+ }
+ return UserHandle.getUid(userId, appId);
+ }
+
private long getApksSize(File apkDir) {
// TODO(b/249294752): also count apk sizes for failed installs
final AtomicLong apksSize = new AtomicLong();
@@ -218,9 +228,9 @@
final int[] originalUsers = info.mOrigUsers;
final int[] originalUserTypes = userManagerInternal.getUserTypesForStatsd(originalUsers);
FrameworkStatsLog.write(FrameworkStatsLog.PACKAGE_UNINSTALLATION_REPORTED,
- info.mUid, removedUsers, removedUserTypes, originalUsers, originalUserTypes,
- deleteFlags, PackageManager.DELETE_SUCCEEDED, info.mIsRemovedPackageSystemUpdate,
- !info.mRemovedForAllUsers);
+ getUid(info.mUid, userId), removedUsers, removedUserTypes, originalUsers,
+ originalUserTypes, deleteFlags, PackageManager.DELETE_SUCCEEDED,
+ info.mIsRemovedPackageSystemUpdate, !info.mRemovedForAllUsers);
final String packageName = info.mRemovedPackage;
final long versionCode = info.mRemovedPackageVersionCode;
reportUninstallationToSecurityLog(packageName, versionCode, userId);
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index 6562de96..53fdfaa 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -1262,6 +1262,12 @@
return pkgState.isApkInUpdatedApex();
}
+ @Nullable
+ @Override
+ public String getApexModuleName() {
+ return pkgState.getApexModuleName();
+ }
+
public PackageSetting setDomainSetId(@NonNull UUID domainSetId) {
mDomainSetId = domainSetId;
onChanged();
@@ -1317,6 +1323,11 @@
return this;
}
+ public PackageSetting setApexModuleName(@Nullable String apexModuleName) {
+ pkgState.setApexModuleName(apexModuleName);
+ return this;
+ }
+
@NonNull
@Override
public PackageStateUnserialized getTransientState() {
diff --git a/services/core/java/com/android/server/pm/ReconcilePackageUtils.java b/services/core/java/com/android/server/pm/ReconcilePackageUtils.java
index 99bcbc9..58dcb02 100644
--- a/services/core/java/com/android/server/pm/ReconcilePackageUtils.java
+++ b/services/core/java/com/android/server/pm/ReconcilePackageUtils.java
@@ -213,8 +213,9 @@
if (sharedUserSetting != null) {
if (sharedUserSetting.signaturesChanged != null
&& !PackageManagerServiceUtils.canJoinSharedUserId(
- parsedPackage.getSigningDetails(),
- sharedUserSetting.getSigningDetails())) {
+ parsedPackage.getPackageName(), parsedPackage.getSigningDetails(),
+ sharedUserSetting,
+ PackageManagerServiceUtils.SHARED_USER_ID_JOIN_TYPE_SYSTEM)) {
if (SystemProperties.getInt("ro.product.first_api_level", 0) <= 29) {
// Mismatched signatures is an error and silently skipping system
// packages will likely break the device in unforeseen ways.
diff --git a/services/core/java/com/android/server/pm/ResolveIntentHelper.java b/services/core/java/com/android/server/pm/ResolveIntentHelper.java
index 970f8ce..a13c568 100644
--- a/services/core/java/com/android/server/pm/ResolveIntentHelper.java
+++ b/services/core/java/com/android/server/pm/ResolveIntentHelper.java
@@ -281,6 +281,7 @@
ri.handleAllWebDataURI = browserCount == n;
ri.activityInfo = new ActivityInfo(ri.activityInfo);
ri.activityInfo.labelRes = ResolverActivity.getLabelRes(intent.getAction());
+ if (ri.userHandle == null) ri.userHandle = UserHandle.of(userId);
// If all of the options come from the same package, show the application's
// label and icon instead of the generic resolver's.
// Some calls like Intent.resolveActivityInfo query the ResolveInfo from here
diff --git a/services/core/java/com/android/server/pm/ScanPartition.java b/services/core/java/com/android/server/pm/ScanPartition.java
index e1d2b3b..9ee6035 100644
--- a/services/core/java/com/android/server/pm/ScanPartition.java
+++ b/services/core/java/com/android/server/pm/ScanPartition.java
@@ -16,13 +16,17 @@
package com.android.server.pm;
+import static com.android.server.pm.PackageManagerService.SCAN_AS_APK_IN_APEX;
+import static com.android.server.pm.PackageManagerService.SCAN_AS_FACTORY;
import static com.android.server.pm.PackageManagerService.SCAN_AS_ODM;
import static com.android.server.pm.PackageManagerService.SCAN_AS_OEM;
import static com.android.server.pm.PackageManagerService.SCAN_AS_PRODUCT;
import static com.android.server.pm.PackageManagerService.SCAN_AS_SYSTEM_EXT;
import static com.android.server.pm.PackageManagerService.SCAN_AS_VENDOR;
+import static com.android.server.pm.PackageManagerService.SCAN_DROP_CACHE;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.pm.PackagePartitions;
import com.android.internal.annotations.VisibleForTesting;
@@ -32,14 +36,18 @@
/**
* List of partitions to be scanned during system boot
*/
-@VisibleForTesting
+@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public class ScanPartition extends PackagePartitions.SystemPartition {
@PackageManagerService.ScanFlags
public final int scanFlag;
+ @Nullable
+ public final ApexManager.ActiveApexInfo apexInfo;
+
public ScanPartition(@NonNull PackagePartitions.SystemPartition partition) {
super(partition);
scanFlag = scanFlagForPartition(partition);
+ apexInfo = null;
}
/**
@@ -48,9 +56,21 @@
* partition along with any specified additional scan flags.
*/
public ScanPartition(@NonNull File folder, @NonNull ScanPartition original,
- @PackageManagerService.ScanFlags int additionalScanFlag) {
+ @Nullable ApexManager.ActiveApexInfo apexInfo) {
super(folder, original);
- this.scanFlag = original.scanFlag | additionalScanFlag;
+ var scanFlags = original.scanFlag;
+ this.apexInfo = apexInfo;
+ if (apexInfo != null) {
+ scanFlags |= SCAN_AS_APK_IN_APEX;
+ if (apexInfo.isFactory) {
+ scanFlags |= SCAN_AS_FACTORY;
+ }
+ if (apexInfo.activeApexChanged) {
+ scanFlags |= SCAN_DROP_CACHE;
+ }
+ }
+ //noinspection WrongConstant
+ this.scanFlag = scanFlags;
}
private static int scanFlagForPartition(PackagePartitions.SystemPartition partition) {
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 97fb0c2..aedf782 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -5052,6 +5052,7 @@
pw.print(prefix); pw.print(" privatePkgFlags="); printFlags(pw, ps.getPrivateFlags(),
PRIVATE_FLAG_DUMP_SPEC);
pw.println();
+ pw.print(prefix); pw.print(" apexModuleName="); pw.println(ps.getApexModuleName());
if (pkg != null && pkg.getOverlayTarget() != null) {
pw.print(prefix); pw.print(" overlayTarget="); pw.println(pkg.getOverlayTarget());
@@ -5263,7 +5264,8 @@
&& !packageName.equals(ps.getPackageName())) {
continue;
}
- if (ps.getPkg() != null && ps.getPkg().isApex()) {
+ if (ps.getPkg() != null && ps.getPkg().isApex()
+ && !dumpState.isOptionEnabled(DumpState.OPTION_INCLUDE_APEX)) {
// Filter APEX packages which will be dumped in the APEX section
continue;
}
@@ -5319,7 +5321,8 @@
&& !packageName.equals(ps.getPackageName())) {
continue;
}
- if (ps.getPkg() != null && ps.getPkg().isApex()) {
+ if (ps.getPkg() != null && ps.getPkg().isApex()
+ && !dumpState.isOptionEnabled(DumpState.OPTION_INCLUDE_APEX)) {
// Filter APEX packages which will be dumped in the APEX section
continue;
}
diff --git a/services/core/java/com/android/server/pm/StorageEventHelper.java b/services/core/java/com/android/server/pm/StorageEventHelper.java
index 4f7c2bd..23156d1 100644
--- a/services/core/java/com/android/server/pm/StorageEventHelper.java
+++ b/services/core/java/com/android/server/pm/StorageEventHelper.java
@@ -158,7 +158,7 @@
final AndroidPackage pkg;
try {
pkg = installPackageHelper.scanSystemPackageTracedLI(
- ps.getPath(), parseFlags, SCAN_INITIAL);
+ ps.getPath(), parseFlags, SCAN_INITIAL, null);
loaded.add(pkg);
} catch (PackageManagerException e) {
diff --git a/services/core/java/com/android/server/pm/UserManagerInternal.java b/services/core/java/com/android/server/pm/UserManagerInternal.java
index 2ae8b52..1787116 100644
--- a/services/core/java/com/android/server/pm/UserManagerInternal.java
+++ b/services/core/java/com/android/server/pm/UserManagerInternal.java
@@ -388,8 +388,8 @@
* and the user is {@link UserManager#isUserVisible() visible}.
*
* <p><b>NOTE: </b>this method is meant to be used only by {@code UserController} (when a user
- * is started). If other clients (like {@code CarService} need to explicitly change the user /
- * display assignment, we'll need to provide other APIs.
+ * is started); for extra unassignments, callers should call {@link
+ * #assignUserToExtraDisplay(int, int)} instead.
*
* <p><b>NOTE: </b>this method doesn't validate if the display exists, it's up to the caller to
* pass a valid display id.
@@ -398,15 +398,43 @@
@UserIdInt int profileGroupId, @UserStartMode int userStartMode, int displayId);
/**
+ * Assigns an extra display to the given user, so the user is visible on that display.
+ *
+ * <p>This method is meant to be used on automotive builds where a passenger zone has more than
+ * one display (for example, the "main" display and a smaller display used for input).
+ *
+ * <p><b>NOTE: </b>this call will be ignored on devices that do not
+ * {@link UserManager#isVisibleBackgroundUsersSupported() support visible background users}.
+ *
+ * @return whether the operation succeeded, in which case the user would be visible on the
+ * display.
+ */
+ public abstract boolean assignUserToExtraDisplay(@UserIdInt int userId, int displayId);
+
+ /**
* Unassigns a user from its current display when it's stopping.
*
* <p><b>NOTE: </b>this method is meant to be used only by {@code UserController} (when a user
- * is stopped). If other clients (like {@code CarService} need to explicitly change the user /
- * display assignment, we'll need to provide other APIs.
+ * is stopped); for extra unassignments, callers should call
+ * {@link #unassignUserFromExtraDisplay(int, int)} instead.
*/
public abstract void unassignUserFromDisplayOnStop(@UserIdInt int userId);
/**
+ * Unassigns the extra display from the given user.
+ *
+ * <p>This method is meant to be used on automotive builds where a passenger zone has more than
+ * one display (for example, the "main" display and a smaller display used for input).
+ *
+ * <p><b>NOTE: </b>this call will be ignored on devices that do not
+ * {@link UserManager#isVisibleBackgroundUsersSupported() support visible background users}.
+ *
+ * @return whether the operation succeeded, i.e., the user was previously
+ * {@link #assignUserToExtraDisplay(int, int) assigned to an extra display}.
+ */
+ public abstract boolean unassignUserFromExtraDisplay(@UserIdInt int userId, int displayId);
+
+ /**
* Returns {@code true} if the user is visible (as defined by
* {@link UserManager#isUserVisible()}.
*/
@@ -485,4 +513,20 @@
* @see UserManager#isMainUser()
*/
public abstract @UserIdInt int getMainUserId();
+
+ /**
+ * Returns the id of the user which should be in the foreground after boot completes.
+ *
+ * <p>If a boot user has been provided by calling {@link UserManager#setBootUser}, the
+ * returned value will be whatever was specified, as long as that user exists and can be
+ * switched to.
+ *
+ * <p>Otherwise, in {@link UserManager#isHeadlessSystemUserMode() headless system user mode},
+ * this will be the user who was last in the foreground on this device. If there is no
+ * switchable user on the device, a new user will be created and its id will be returned.
+ *
+ * <p>In non-headless system user mode, the return value will be {@link UserHandle#USER_SYSTEM}.
+ */
+ public abstract @UserIdInt int getBootUser()
+ throws UserManager.CheckedUserOperationException;
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 81f83b0..4b936c1 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -21,6 +21,7 @@
import static android.os.UserManager.DEV_CREATE_OVERRIDE_PROPERTY;
import static android.os.UserManager.DISALLOW_USER_SWITCH;
import static android.os.UserManager.SYSTEM_USER_MODE_EMULATION_PROPERTY;
+import static android.os.UserManager.USER_OPERATION_ERROR_UNKNOWN;
import android.Manifest;
import android.accounts.Account;
@@ -254,7 +255,8 @@
| UserInfo.FLAG_RESTRICTED
| UserInfo.FLAG_GUEST
| UserInfo.FLAG_DEMO
- | UserInfo.FLAG_FULL;
+ | UserInfo.FLAG_FULL
+ | UserInfo.FLAG_FOR_TESTING;
@VisibleForTesting
static final int MIN_USER_ID = UserHandle.MIN_SECONDARY_USER_ID;
@@ -637,6 +639,9 @@
private final UserVisibilityMediator mUserVisibilityMediator;
+ @GuardedBy("mUsersLock")
+ private @UserIdInt int mBootUser = UserHandle.USER_NULL;
+
private static UserManagerService sInstance;
public static UserManagerService getInstance() {
@@ -936,6 +941,26 @@
}
@Override
+ public void setBootUser(@UserIdInt int userId) {
+ checkCreateUsersPermission("Set boot user");
+ synchronized (mUsersLock) {
+ // TODO(b/263381643): Change to EventLog.
+ Slogf.i(LOG_TAG, "setBootUser %d", userId);
+ mBootUser = userId;
+ }
+ }
+
+ @Override
+ public @UserIdInt int getBootUser() {
+ checkCreateUsersPermission("Get boot user");
+ try {
+ return mLocalService.getBootUser();
+ } catch (UserManager.CheckedUserOperationException e) {
+ throw e.toServiceSpecificException();
+ }
+ }
+
+ @Override
public int getPreviousFullUserToEnterForeground() {
checkQueryOrCreateUsersPermission("get previous user");
int previousUser = UserHandle.USER_NULL;
@@ -1476,20 +1501,15 @@
@Override
public void revokeUserAdmin(@UserIdInt int userId) {
checkManageUserAndAcrossUsersFullPermission("revoke admin privileges");
-
synchronized (mPackagesLock) {
- UserInfo info;
synchronized (mUsersLock) {
- info = getUserInfoLU(userId);
- }
- if (info == null || !info.isAdmin()) {
- // Exit if no user found with that id, or the user is not an Admin.
- return;
- }
-
- info.flags ^= UserInfo.FLAG_ADMIN;
- synchronized (mUsersLock) {
- writeUserLP(getUserDataLU(info.id));
+ UserData user = getUserDataLU(userId);
+ if (user == null || !user.info.isAdmin()) {
+ // Exit if no user found with that id, or the user is not an Admin.
+ return;
+ }
+ user.info.flags ^= UserInfo.FLAG_ADMIN;
+ writeUserLP(user);
}
}
}
@@ -1574,6 +1594,8 @@
Slog.w(LOG_TAG, "System user instantiated at least " + number + " times");
}
name = getOwnerName();
+ } else if (orig.isMain()) {
+ name = getOwnerName();
} else if (orig.isGuest()) {
name = getGuestName();
}
@@ -1834,23 +1856,6 @@
}
/**
- * Gets the current user id, or the target user id in case there is a started user switch.
- *
- * @return id of current or target foreground user, or {@link UserHandle#USER_NULL} if
- * {@link ActivityManagerInternal} is not available yet.
- */
- @VisibleForTesting
- int getCurrentOrTargetUserId() {
- ActivityManagerInternal activityManagerInternal = getActivityManagerInternal();
- if (activityManagerInternal == null) {
- Slog.w(LOG_TAG, "getCurrentOrTargetUserId() called too early, ActivityManagerInternal"
- + " is not set yet");
- return UserHandle.USER_NULL;
- }
- return activityManagerInternal.getCurrentUser().id;
- }
-
- /**
* Gets whether the user is the current foreground user or a started profile of that user.
*
* <p>Doesn't perform any permission check.
@@ -4557,7 +4562,7 @@
UserHandle.USER_NULL, null);
if (userInfo == null) {
- throw new ServiceSpecificException(UserManager.USER_OPERATION_ERROR_UNKNOWN);
+ throw new ServiceSpecificException(USER_OPERATION_ERROR_UNKNOWN);
}
} catch (UserManager.CheckedUserOperationException e) {
throw e.toServiceSpecificException();
@@ -4686,7 +4691,7 @@
if (parent == null) {
throwCheckedUserOperationException(
"Cannot find user data for parent user " + parentId,
- UserManager.USER_OPERATION_ERROR_UNKNOWN);
+ USER_OPERATION_ERROR_UNKNOWN);
}
}
if (!preCreate && !canAddMoreUsersOfType(userTypeDetails)) {
@@ -4714,7 +4719,7 @@
&& !isCreationOverrideEnabled()) {
throwCheckedUserOperationException(
"Cannot add restricted profile - parent user must be system",
- UserManager.USER_OPERATION_ERROR_UNKNOWN);
+ USER_OPERATION_ERROR_UNKNOWN);
}
userId = getNextAvailableId();
@@ -5424,7 +5429,8 @@
final long ident = Binder.clearCallingIdentity();
try {
final UserData userData;
- if (userId == getCurrentOrTargetUserId()) {
+ int currentUser = getCurrentUserId();
+ if (currentUser == userId) {
Slog.w(LOG_TAG, "Current user cannot be removed.");
return false;
}
@@ -6480,6 +6486,9 @@
if (DBG_ALLOCATION) {
pw.println(" System user allocations: " + mUser0Allocations.get());
}
+ synchronized (mUsersLock) {
+ pw.println(" Boot user: " + mBootUser);
+ }
pw.println();
pw.println("Number of listeners for");
@@ -6672,6 +6681,18 @@
return mLocalService.isUserInitialized(userId);
}
+ /**
+ * Creates a new user, intended to be the initial user on a device in headless system user mode.
+ */
+ private UserInfo createInitialUserForHsum() throws UserManager.CheckedUserOperationException {
+ final int flags = UserInfo.FLAG_ADMIN | UserInfo.FLAG_MAIN;
+
+ // Null name will be replaced with "Owner" on-demand to allow for localisation.
+ return createUserInternalUnchecked(/* name= */ null, UserManager.USER_TYPE_FULL_SECONDARY,
+ flags, UserHandle.USER_NULL, /* preCreate= */ false,
+ /* disallowedPackages= */ null, /* token= */ null);
+ }
+
private class LocalService extends UserManagerInternal {
@Override
public void setDevicePolicyUserRestrictions(@UserIdInt int originatingUserId,
@@ -7043,6 +7064,16 @@
}
@Override
+ public boolean assignUserToExtraDisplay(int userId, int displayId) {
+ return mUserVisibilityMediator.assignUserToExtraDisplay(userId, displayId);
+ }
+
+ @Override
+ public boolean unassignUserFromExtraDisplay(int userId, int displayId) {
+ return mUserVisibilityMediator.unassignUserFromExtraDisplay(userId, displayId);
+ }
+
+ @Override
public void unassignUserFromDisplayOnStop(@UserIdInt int userId) {
mUserVisibilityMediator.unassignUserFromDisplayOnStop(userId);
}
@@ -7105,6 +7136,56 @@
return getMainUserIdUnchecked();
}
+ @Override
+ public @UserIdInt int getBootUser() throws UserManager.CheckedUserOperationException {
+ synchronized (mUsersLock) {
+ // TODO(b/242195409): On Automotive, block if boot user not provided.
+ if (mBootUser != UserHandle.USER_NULL) {
+ final UserData userData = mUsers.get(mBootUser);
+ if (userData != null && userData.info.supportsSwitchToByUser()) {
+ Slogf.i(LOG_TAG, "Using provided boot user: %d", mBootUser);
+ return mBootUser;
+ } else {
+ Slogf.w(LOG_TAG,
+ "Provided boot user cannot be switched to: %d", mBootUser);
+ }
+ }
+ }
+
+ if (isHeadlessSystemUserMode()) {
+ // Return the previous foreground user, if there is one.
+ final int previousUser = getPreviousFullUserToEnterForeground();
+ if (previousUser != UserHandle.USER_NULL) {
+ Slogf.i(LOG_TAG, "Boot user is previous user %d", previousUser);
+ return previousUser;
+ }
+ // No previous user. Return the first switchable user if there is one.
+ synchronized (mUsersLock) {
+ final int userSize = mUsers.size();
+ for (int i = 0; i < userSize; i++) {
+ final UserData userData = mUsers.valueAt(i);
+ if (userData.info.supportsSwitchToByUser()) {
+ int firstSwitchable = userData.info.id;
+ Slogf.i(LOG_TAG,
+ "Boot user is first switchable user %d", firstSwitchable);
+ return firstSwitchable;
+ }
+ }
+ }
+ // No switchable users. Create the initial user.
+ final UserInfo newInitialUser = createInitialUserForHsum();
+ if (newInitialUser == null) {
+ throw new UserManager.CheckedUserOperationException(
+ "Initial user creation failed", USER_OPERATION_ERROR_UNKNOWN);
+ }
+ Slogf.i(LOG_TAG,
+ "No switchable users. Boot user is new user %d", newInitialUser.id);
+ return newInitialUser.id;
+ }
+ // Not HSUM, return system user.
+ return UserHandle.USER_SYSTEM;
+ }
+
} // class LocalService
@@ -7124,7 +7205,7 @@
+ restriction + " is enabled.";
Slog.w(LOG_TAG, errorMessage);
throw new UserManager.CheckedUserOperationException(errorMessage,
- UserManager.USER_OPERATION_ERROR_UNKNOWN);
+ USER_OPERATION_ERROR_UNKNOWN);
}
}
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 27d74d5..214fd61 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -149,7 +149,8 @@
UserManager.DISALLOW_WIFI_DIRECT,
UserManager.DISALLOW_ADD_WIFI_CONFIG,
UserManager.DISALLOW_CELLULAR_2G,
- UserManager.DISALLOW_ULTRA_WIDEBAND_RADIO
+ UserManager.DISALLOW_ULTRA_WIDEBAND_RADIO,
+ UserManager.DISALLOW_CONFIG_DEFAULT_APPS
});
public static final Set<String> DEPRECATED_USER_RESTRICTIONS = Sets.newArraySet(
diff --git a/services/core/java/com/android/server/pm/UserVisibilityMediator.java b/services/core/java/com/android/server/pm/UserVisibilityMediator.java
index d8e4dac..66d390f 100644
--- a/services/core/java/com/android/server/pm/UserVisibilityMediator.java
+++ b/services/core/java/com/android/server/pm/UserVisibilityMediator.java
@@ -19,6 +19,7 @@
import static android.os.UserHandle.USER_NULL;
import static android.os.UserHandle.USER_SYSTEM;
import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.Display.INVALID_DISPLAY;
import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_FAILURE;
import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE;
@@ -113,7 +114,18 @@
*/
@Nullable
@GuardedBy("mLock")
- private final SparseIntArray mUsersOnDisplaysMap;
+ private final SparseIntArray mUsersAssignedToDisplayOnStart;
+
+ /**
+ * Map of extra (i.e., not assigned on start, but by explicit calls to
+ * {@link #assignUserToExtraDisplay(int, int)}) displays assigned to user (key is display id,
+ * value is user id).
+ *
+ * <p>Only set when {@code mUsersOnSecondaryDisplaysEnabled} is {@code true}.
+ */
+ @Nullable
+ @GuardedBy("mLock")
+ private final SparseIntArray mExtraDisplaysAssignedToUsers;
/**
* Mapping from each started user to its profile group.
@@ -137,7 +149,13 @@
@VisibleForTesting
UserVisibilityMediator(boolean backgroundUsersOnDisplaysEnabled, Handler handler) {
mVisibleBackgroundUsersEnabled = backgroundUsersOnDisplaysEnabled;
- mUsersOnDisplaysMap = mVisibleBackgroundUsersEnabled ? new SparseIntArray() : null;
+ if (mVisibleBackgroundUsersEnabled) {
+ mUsersAssignedToDisplayOnStart = new SparseIntArray();
+ mExtraDisplaysAssignedToUsers = new SparseIntArray();
+ } else {
+ mUsersAssignedToDisplayOnStart = null;
+ mExtraDisplaysAssignedToUsers = null;
+ }
mHandler = handler;
// TODO(b/242195409): might need to change this if boot logic is refactored for HSUM devices
mStartedProfileGroupIds.put(INITIAL_CURRENT_USER_ID, INITIAL_CURRENT_USER_ID);
@@ -207,7 +225,7 @@
if (DBG) {
Slogf.d(TAG, "adding user / display mapping (%d -> %d)", userId, displayId);
}
- mUsersOnDisplaysMap.put(userId, displayId);
+ mUsersAssignedToDisplayOnStart.put(userId, displayId);
break;
case SECONDARY_DISPLAY_MAPPING_NOT_NEEDED:
if (DBG) {
@@ -341,9 +359,9 @@
}
// Check if display is available
- for (int i = 0; i < mUsersOnDisplaysMap.size(); i++) {
- int assignedUserId = mUsersOnDisplaysMap.keyAt(i);
- int assignedDisplayId = mUsersOnDisplaysMap.valueAt(i);
+ for (int i = 0; i < mUsersAssignedToDisplayOnStart.size(); i++) {
+ int assignedUserId = mUsersAssignedToDisplayOnStart.keyAt(i);
+ int assignedDisplayId = mUsersAssignedToDisplayOnStart.valueAt(i);
if (DBG) {
Slogf.d(TAG, "%d: assignedUserId=%d, assignedDisplayId=%d",
i, assignedUserId, assignedDisplayId);
@@ -363,6 +381,100 @@
}
/**
+ * See {@link UserManagerInternal#assignUserToExtraDisplay(int, int)}.
+ */
+ public boolean assignUserToExtraDisplay(@UserIdInt int userId, int displayId) {
+ if (DBG) {
+ Slogf.d(TAG, "assignUserToExtraDisplay(%d, %d)", userId, displayId);
+ }
+ if (!mVisibleBackgroundUsersEnabled) {
+ Slogf.w(TAG, "assignUserToExtraDisplay(%d, %d): called when not supported", userId,
+ displayId);
+ return false;
+ }
+ if (displayId == INVALID_DISPLAY) {
+ Slogf.w(TAG, "assignUserToExtraDisplay(%d, %d): called with INVALID_DISPLAY", userId,
+ displayId);
+ return false;
+ }
+ if (displayId == DEFAULT_DISPLAY) {
+ Slogf.w(TAG, "assignUserToExtraDisplay(%d, %d): DEFAULT_DISPLAY is automatically "
+ + "assigned to current user", userId, displayId);
+ return false;
+ }
+
+ synchronized (mLock) {
+ if (!isUserVisible(userId)) {
+ Slogf.w(TAG, "assignUserToExtraDisplay(%d, %d): failed because user is not visible",
+ userId, displayId);
+ return false;
+ }
+ if (isStartedProfile(userId)) {
+ Slogf.w(TAG, "assignUserToExtraDisplay(%d, %d): failed because user is a profile",
+ userId, displayId);
+ return false;
+ }
+
+ if (mExtraDisplaysAssignedToUsers.get(displayId, USER_NULL) == userId) {
+ Slogf.w(TAG, "assignUserToExtraDisplay(%d, %d): failed because user is already "
+ + "assigned to that display", userId, displayId);
+ return false;
+ }
+
+ int userAssignedToDisplay = getUserAssignedToDisplay(displayId,
+ /* returnCurrentUserByDefault= */ false);
+ if (userAssignedToDisplay != USER_NULL) {
+ Slogf.w(TAG, "assignUserToExtraDisplay(%d, %d): failed because display was assigned"
+ + " to user %d on start", userId, displayId, userAssignedToDisplay);
+ return false;
+ }
+ userAssignedToDisplay = mExtraDisplaysAssignedToUsers.get(userId, USER_NULL);
+ if (userAssignedToDisplay != USER_NULL) {
+ Slogf.w(TAG, "assignUserToExtraDisplay(%d, %d): failed because user %d was already "
+ + "assigned that extra display", userId, displayId, userAssignedToDisplay);
+ return false;
+ }
+ if (DBG) {
+ Slogf.d(TAG, "addding %d -> %d to map", displayId, userId);
+ }
+ mExtraDisplaysAssignedToUsers.put(displayId, userId);
+ }
+ return true;
+ }
+
+ /**
+ * See {@link UserManagerInternal#unassignUserFromExtraDisplay(int, int)}.
+ */
+ public boolean unassignUserFromExtraDisplay(@UserIdInt int userId, int displayId) {
+ if (DBG) {
+ Slogf.d(TAG, "unassignUserFromExtraDisplay(%d, %d)", userId, displayId);
+ }
+ if (!mVisibleBackgroundUsersEnabled) {
+ Slogf.w(TAG, "unassignUserFromExtraDisplay(%d, %d): called when not supported",
+ userId, displayId);
+ return false;
+ }
+ synchronized (mLock) {
+ int assignedUserId = mExtraDisplaysAssignedToUsers.get(displayId, USER_NULL);
+ if (assignedUserId == USER_NULL) {
+ Slogf.w(TAG, "unassignUserFromExtraDisplay(%d, %d): not assigned to any user",
+ userId, displayId);
+ return false;
+ }
+ if (assignedUserId != userId) {
+ Slogf.w(TAG, "unassignUserFromExtraDisplay(%d, %d): was assigned to user %d",
+ userId, displayId, assignedUserId);
+ return false;
+ }
+ if (DBG) {
+ Slogf.d(TAG, "removing %d from map", displayId);
+ }
+ mExtraDisplaysAssignedToUsers.delete(displayId);
+ }
+ return true;
+ }
+
+ /**
* See {@link UserManagerInternal#unassignUserFromDisplayOnStop(int)}.
*/
public void unassignUserFromDisplayOnStop(@UserIdInt int userId) {
@@ -373,7 +485,7 @@
synchronized (mLock) {
visibleUsersBefore = getVisibleUsers();
- unassignUserFromDisplayOnStopLocked(userId);
+ unassignUserFromAllDisplaysOnStopLocked(userId);
visibleUsersAfter = getVisibleUsers();
}
@@ -381,7 +493,7 @@
}
@GuardedBy("mLock")
- private void unassignUserFromDisplayOnStopLocked(@UserIdInt int userId) {
+ private void unassignUserFromAllDisplaysOnStopLocked(@UserIdInt int userId) {
if (DBG) {
Slogf.d(TAG, "Removing %d from mStartedProfileGroupIds (%s)", userId,
mStartedProfileGroupIds);
@@ -395,10 +507,21 @@
return;
}
if (DBG) {
- Slogf.d(TAG, "Removing %d from mUsersOnSecondaryDisplays (%s)", userId,
- mUsersOnDisplaysMap);
+ Slogf.d(TAG, "Removing user %d from mUsersOnDisplaysMap (%s)", userId,
+ mUsersAssignedToDisplayOnStart);
}
- mUsersOnDisplaysMap.delete(userId);
+ mUsersAssignedToDisplayOnStart.delete(userId);
+
+ // Remove extra displays as well
+ for (int i = mExtraDisplaysAssignedToUsers.size() - 1; i >= 0; i--) {
+ if (mExtraDisplaysAssignedToUsers.valueAt(i) == userId) {
+ if (DBG) {
+ Slogf.d(TAG, "Removing display %d from mExtraDisplaysAssignedToUsers (%s)",
+ mExtraDisplaysAssignedToUsers.keyAt(i), mExtraDisplaysAssignedToUsers);
+ }
+ mExtraDisplaysAssignedToUsers.removeAt(i);
+ }
+ }
}
/**
@@ -424,7 +547,7 @@
boolean visible;
synchronized (mLock) {
- visible = mUsersOnDisplaysMap.indexOfKey(userId) >= 0;
+ visible = mUsersAssignedToDisplayOnStart.indexOfKey(userId) >= 0;
}
if (DBG) {
Slogf.d(TAG, "isUserVisible(%d): %b from mapping", userId, visible);
@@ -448,7 +571,12 @@
}
synchronized (mLock) {
- return mUsersOnDisplaysMap.get(userId, Display.INVALID_DISPLAY) == displayId;
+ if (mUsersAssignedToDisplayOnStart.get(userId, Display.INVALID_DISPLAY) == displayId) {
+ // User assigned to display on start
+ return true;
+ }
+ // Check for extra assignment
+ return mExtraDisplaysAssignedToUsers.get(displayId, USER_NULL) == userId;
}
}
@@ -465,24 +593,34 @@
}
synchronized (mLock) {
- return mUsersOnDisplaysMap.get(userId, Display.INVALID_DISPLAY);
+ return mUsersAssignedToDisplayOnStart.get(userId, Display.INVALID_DISPLAY);
}
}
/**
* See {@link UserManagerInternal#getUserAssignedToDisplay(int)}.
*/
- public int getUserAssignedToDisplay(@UserIdInt int displayId) {
- if (displayId == Display.DEFAULT_DISPLAY || !mVisibleBackgroundUsersEnabled) {
+ public @UserIdInt int getUserAssignedToDisplay(@UserIdInt int displayId) {
+ return getUserAssignedToDisplay(displayId, /* returnCurrentUserByDefault= */ true);
+ }
+
+ /**
+ * Gets the user explicitly assigned to a display, or the current user when no user is assigned
+ * to it (and {@code returnCurrentUserByDefault} is {@code true}).
+ */
+ private @UserIdInt int getUserAssignedToDisplay(@UserIdInt int displayId,
+ boolean returnCurrentUserByDefault) {
+ if (returnCurrentUserByDefault
+ && (displayId == Display.DEFAULT_DISPLAY || !mVisibleBackgroundUsersEnabled)) {
return getCurrentUserId();
}
synchronized (mLock) {
- for (int i = 0; i < mUsersOnDisplaysMap.size(); i++) {
- if (mUsersOnDisplaysMap.valueAt(i) != displayId) {
+ for (int i = 0; i < mUsersAssignedToDisplayOnStart.size(); i++) {
+ if (mUsersAssignedToDisplayOnStart.valueAt(i) != displayId) {
continue;
}
- int userId = mUsersOnDisplaysMap.keyAt(i);
+ int userId = mUsersAssignedToDisplayOnStart.keyAt(i);
if (!isStartedProfile(userId)) {
return userId;
} else if (DBG) {
@@ -491,6 +629,13 @@
}
}
}
+ if (!returnCurrentUserByDefault) {
+ if (DBG) {
+ Slogf.d(TAG, "getUserAssignedToDisplay(%d): no user assigned to display, returning "
+ + "USER_NULL instead", displayId);
+ }
+ return USER_NULL;
+ }
int currentUserId = getCurrentUserId();
if (DBG) {
@@ -618,9 +763,11 @@
ipw.print("Supports visible background users on displays: ");
ipw.println(mVisibleBackgroundUsersEnabled);
- if (mUsersOnDisplaysMap != null) {
- dumpSparseIntArray(ipw, mUsersOnDisplaysMap, "user / display", "u", "d");
- }
+ dumpSparseIntArray(ipw, mUsersAssignedToDisplayOnStart, "user / display", "u", "d");
+
+ dumpSparseIntArray(ipw, mExtraDisplaysAssignedToUsers, "extra display / user",
+ "d", "u");
+
int numberListeners = mListeners.size();
ipw.print("Number of listeners: ");
ipw.println(numberListeners);
@@ -638,8 +785,14 @@
ipw.decreaseIndent();
}
- private static void dumpSparseIntArray(IndentingPrintWriter ipw, SparseIntArray array,
+ private static void dumpSparseIntArray(IndentingPrintWriter ipw, @Nullable SparseIntArray array,
String arrayDescription, String keyName, String valueName) {
+ if (array == null) {
+ ipw.print("No ");
+ ipw.print(arrayDescription);
+ ipw.println(" mappings");
+ return;
+ }
ipw.print("Number of ");
ipw.print(arrayDescription);
ipw.print(" mappings: ");
diff --git a/services/core/java/com/android/server/pm/dex/DexoptOptions.java b/services/core/java/com/android/server/pm/dex/DexoptOptions.java
index 411c19f..d3fba7c 100644
--- a/services/core/java/com/android/server/pm/dex/DexoptOptions.java
+++ b/services/core/java/com/android/server/pm/dex/DexoptOptions.java
@@ -24,7 +24,7 @@
import com.android.server.art.ReasonMapping;
import com.android.server.art.model.ArtFlags;
-import com.android.server.art.model.OptimizeParams;
+import com.android.server.art.model.DexoptParams;
import com.android.server.pm.DexOptHelper;
import com.android.server.pm.PackageManagerService;
@@ -201,22 +201,22 @@
}
/**
- * Returns an {@link OptimizeParams} instance corresponding to this object, for use with
+ * Returns an {@link DexoptParams} instance corresponding to this object, for use with
* {@link com.android.server.art.ArtManagerLocal}.
*
- * @param extraFlags extra {@link ArtFlags#OptimizeFlags} to set in the returned
- * {@code OptimizeParams} beyond those converted from this object
+ * @param extraFlags extra {@link ArtFlags#DexoptFlags} to set in the returned
+ * {@code DexoptParams} beyond those converted from this object
* @return null if the settings cannot be accurately represented, and hence the old
* PackageManager/installd code paths need to be used.
*/
- public @Nullable OptimizeParams convertToOptimizeParams(/*@OptimizeFlags*/ int extraFlags) {
+ public @Nullable DexoptParams convertToDexoptParams(/*@DexoptFlags*/ int extraFlags) {
if (mSplitName != null) {
DexOptHelper.reportArtManagerFallback(
mPackageName, "Request to optimize only split " + mSplitName);
return null;
}
- /*@OptimizeFlags*/ int flags = extraFlags;
+ /*@DexoptFlags*/ int flags = extraFlags;
if ((mFlags & DEXOPT_CHECK_FOR_PROFILES_UPDATES) == 0
&& isProfileGuidedCompilerFilter(mCompilerFilter)) {
// ART Service doesn't support bypassing the profile update check when profiles are
@@ -322,7 +322,7 @@
"Invalid compilation reason " + mCompilationReason);
}
- return new OptimizeParams.Builder(reason, flags)
+ return new DexoptParams.Builder(reason, flags)
.setCompilerFilter(mCompilerFilter)
.setPriorityClass(priority)
.build();
diff --git a/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java b/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java
index 1778e57..d7c4a09 100644
--- a/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java
+++ b/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java
@@ -1810,6 +1810,11 @@
}
@Override
+ public boolean isAllowUpdateOwnership() {
+ return getBoolean2(Booleans2.ALLOW_UPDATE_OWNERSHIP);
+ }
+
+ @Override
public boolean isVmSafeMode() {
return getBoolean(Booleans.VM_SAFE_MODE);
}
@@ -2513,6 +2518,11 @@
}
@Override
+ public PackageImpl setAllowUpdateOwnership(boolean value) {
+ return setBoolean2(Booleans2.ALLOW_UPDATE_OWNERSHIP, value);
+ }
+
+ @Override
public PackageImpl sortActivities() {
Collections.sort(this.activities, ORDER_COMPARATOR);
return this;
@@ -3726,5 +3736,6 @@
private static final long STUB = 1L;
private static final long APEX = 1L << 1;
+ private static final long ALLOW_UPDATE_OWNERSHIP = 1L << 2;
}
}
diff --git a/services/core/java/com/android/server/pm/permission/Permission.java b/services/core/java/com/android/server/pm/permission/Permission.java
index f3b9246..c81d6d7 100644
--- a/services/core/java/com/android/server/pm/permission/Permission.java
+++ b/services/core/java/com/android/server/pm/permission/Permission.java
@@ -105,6 +105,15 @@
mType = type;
}
+ public Permission(@NonNull PermissionInfo permissionInfo, @PermissionType int type,
+ boolean reconciled, int uid, int[] gids, boolean gidsPerUser) {
+ this(permissionInfo, type);
+ mReconciled = reconciled;
+ mUid = uid;
+ mGids = gids;
+ mGidsPerUser = gidsPerUser;
+ }
+
@NonNull
public PermissionInfo getPermissionInfo() {
return mPermissionInfo;
diff --git a/services/core/java/com/android/server/pm/pkg/AndroidPackage.java b/services/core/java/com/android/server/pm/pkg/AndroidPackage.java
index 78091bc..ad73873 100644
--- a/services/core/java/com/android/server/pm/pkg/AndroidPackage.java
+++ b/services/core/java/com/android/server/pm/pkg/AndroidPackage.java
@@ -1483,4 +1483,10 @@
* @hide
*/
boolean isVisibleToInstantApps();
+
+ /**
+ * @see R.styleable#AndroidManifest_allowUpdateOwnership
+ * @hide
+ */
+ boolean isAllowUpdateOwnership();
}
diff --git a/services/core/java/com/android/server/pm/pkg/PackageState.java b/services/core/java/com/android/server/pm/pkg/PackageState.java
index 5fdead0..a12c9d0 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageState.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageState.java
@@ -417,4 +417,11 @@
* @hide
*/
boolean isVendor();
+
+ /**
+ * The name of the APEX module containing this package, if it is an APEX or APK-in-APEX.
+ * @hide
+ */
+ @Nullable
+ String getApexModuleName();
}
diff --git a/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java b/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java
index 8dee8ee..bc6dab4 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java
@@ -154,6 +154,8 @@
private final SigningInfo mSigningInfo;
@NonNull
private final SparseArray<PackageUserState> mUserStates;
+ @Nullable
+ private final String mApexModuleName;
private PackageStateImpl(@NonNull PackageState pkgState, @Nullable AndroidPackage pkg) {
mAndroidPackage = pkg;
@@ -206,6 +208,8 @@
mUserStates.put(userStates.keyAt(index),
UserStateImpl.copy(userStates.valueAt(index)));
}
+
+ mApexModuleName = pkgState.getApexModuleName();
}
@NonNull
@@ -714,6 +718,11 @@
}
@DataClass.Generated.Member
+ public @Nullable String getApexModuleName() {
+ return mApexModuleName;
+ }
+
+ @DataClass.Generated.Member
public @NonNull PackageStateImpl setBooleans( int value) {
mBooleans = value;
return this;
@@ -723,7 +732,7 @@
time = 1671671043929L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java",
- inputSignatures = "private int mBooleans\nprivate final @android.annotation.Nullable com.android.server.pm.pkg.AndroidPackage mAndroidPackage\nprivate final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.Nullable java.lang.String mVolumeUuid\nprivate final int mAppId\nprivate final int mCategoryOverride\nprivate final @android.annotation.Nullable java.lang.String mCpuAbiOverride\nprivate final @android.content.pm.ApplicationInfo.HiddenApiEnforcementPolicy int mHiddenApiEnforcementPolicy\nprivate final long mLastModifiedTime\nprivate final long mLastUpdateTime\nprivate final long mLongVersionCode\nprivate final @android.annotation.NonNull java.util.Map<java.lang.String,java.util.Set<java.lang.String>> mMimeGroups\nprivate final @android.annotation.NonNull java.io.File mPath\nprivate final @android.annotation.Nullable java.lang.String mPrimaryCpuAbi\nprivate final @android.annotation.Nullable java.lang.String mSecondaryCpuAbi\nprivate final @android.annotation.Nullable java.lang.String mSeInfo\nprivate final boolean mHasSharedUser\nprivate final int mSharedUserAppId\nprivate final @android.annotation.NonNull java.lang.String[] mUsesSdkLibraries\nprivate final @android.annotation.NonNull long[] mUsesSdkLibrariesVersionsMajor\nprivate final @android.annotation.NonNull java.lang.String[] mUsesStaticLibraries\nprivate final @android.annotation.NonNull long[] mUsesStaticLibrariesVersions\nprivate final @android.annotation.NonNull java.util.List<com.android.server.pm.pkg.SharedLibrary> mUsesLibraries\nprivate final @android.annotation.NonNull java.util.List<java.lang.String> mUsesLibraryFiles\nprivate final @android.annotation.NonNull long[] mLastPackageUsageTime\nprivate final @android.annotation.NonNull android.content.pm.SigningInfo mSigningInfo\nprivate final @android.annotation.NonNull android.util.SparseArray<com.android.server.pm.pkg.PackageUserState> mUserStates\npublic static com.android.server.pm.pkg.PackageState copy(com.android.server.pm.pkg.PackageStateInternal)\nprivate void setBoolean(int,boolean)\nprivate boolean getBoolean(int)\npublic @android.annotation.NonNull @java.lang.Override com.android.server.pm.pkg.PackageUserState getStateForUser(android.os.UserHandle)\npublic @java.lang.Override boolean isExternalStorage()\npublic @java.lang.Override boolean isForceQueryableOverride()\npublic @java.lang.Override boolean isHiddenUntilInstalled()\npublic @java.lang.Override boolean isInstallPermissionsFixed()\npublic @java.lang.Override boolean isOdm()\npublic @java.lang.Override boolean isOem()\npublic @java.lang.Override boolean isPrivileged()\npublic @java.lang.Override boolean isProduct()\npublic @java.lang.Override boolean isRequiredForSystemUser()\npublic @java.lang.Override boolean isSystem()\npublic @java.lang.Override boolean isSystemExt()\npublic @java.lang.Override boolean isUpdateAvailable()\npublic @java.lang.Override boolean isUpdatedSystemApp()\npublic @java.lang.Override boolean isApkInUpdatedApex()\npublic @java.lang.Override boolean isVendor()\npublic @java.lang.Override long getVersionCode()\npublic @java.lang.Override boolean hasSharedUser()\npublic @java.lang.Override boolean isApex()\nclass PackageStateImpl extends java.lang.Object implements [com.android.server.pm.pkg.PackageState]\nprivate static final int SYSTEM\nprivate static final int EXTERNAL_STORAGE\nprivate static final int PRIVILEGED\nprivate static final int OEM\nprivate static final int VENDOR\nprivate static final int PRODUCT\nprivate static final int SYSTEM_EXT\nprivate static final int REQUIRED_FOR_SYSTEM_USER\nprivate static final int ODM\nprivate static final int FORCE_QUERYABLE_OVERRIDE\nprivate static final int HIDDEN_UNTIL_INSTALLED\nprivate static final int INSTALL_PERMISSIONS_FIXED\nprivate static final int UPDATE_AVAILABLE\nprivate static final int UPDATED_SYSTEM_APP\nprivate static final int APK_IN_UPDATED_APEX\nclass Booleans extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false)")
+ inputSignatures = "private int mBooleans\nprivate final @android.annotation.Nullable com.android.server.pm.pkg.AndroidPackage mAndroidPackage\nprivate final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.Nullable java.lang.String mVolumeUuid\nprivate final int mAppId\nprivate final int mCategoryOverride\nprivate final @android.annotation.Nullable java.lang.String mCpuAbiOverride\nprivate final @android.content.pm.ApplicationInfo.HiddenApiEnforcementPolicy int mHiddenApiEnforcementPolicy\nprivate final long mLastModifiedTime\nprivate final long mLastUpdateTime\nprivate final long mLongVersionCode\nprivate final @android.annotation.NonNull java.util.Map<java.lang.String,java.util.Set<java.lang.String>> mMimeGroups\nprivate final @android.annotation.NonNull java.io.File mPath\nprivate final @android.annotation.Nullable java.lang.String mPrimaryCpuAbi\nprivate final @android.annotation.Nullable java.lang.String mSecondaryCpuAbi\nprivate final @android.annotation.Nullable java.lang.String mSeInfo\nprivate final boolean mHasSharedUser\nprivate final int mSharedUserAppId\nprivate final @android.annotation.NonNull java.lang.String[] mUsesSdkLibraries\nprivate final @android.annotation.NonNull long[] mUsesSdkLibrariesVersionsMajor\nprivate final @android.annotation.NonNull java.lang.String[] mUsesStaticLibraries\nprivate final @android.annotation.NonNull long[] mUsesStaticLibrariesVersions\nprivate final @android.annotation.NonNull java.util.List<com.android.server.pm.pkg.SharedLibrary> mUsesLibraries\nprivate final @android.annotation.NonNull java.util.List<java.lang.String> mUsesLibraryFiles\nprivate final @android.annotation.NonNull long[] mLastPackageUsageTime\nprivate final @android.annotation.NonNull android.content.pm.SigningInfo mSigningInfo\nprivate final @android.annotation.NonNull android.util.SparseArray<com.android.server.pm.pkg.PackageUserState> mUserStates\nprivate final @android.annotation.Nullable java.lang.String mApexModuleName\npublic static com.android.server.pm.pkg.PackageState copy(com.android.server.pm.pkg.PackageStateInternal)\nprivate void setBoolean(int,boolean)\nprivate boolean getBoolean(int)\npublic @android.annotation.NonNull @java.lang.Override com.android.server.pm.pkg.PackageUserState getStateForUser(android.os.UserHandle)\npublic @java.lang.Override boolean isExternalStorage()\npublic @java.lang.Override boolean isForceQueryableOverride()\npublic @java.lang.Override boolean isHiddenUntilInstalled()\npublic @java.lang.Override boolean isInstallPermissionsFixed()\npublic @java.lang.Override boolean isOdm()\npublic @java.lang.Override boolean isOem()\npublic @java.lang.Override boolean isPrivileged()\npublic @java.lang.Override boolean isProduct()\npublic @java.lang.Override boolean isRequiredForSystemUser()\npublic @java.lang.Override boolean isSystem()\npublic @java.lang.Override boolean isSystemExt()\npublic @java.lang.Override boolean isUpdateAvailable()\npublic @java.lang.Override boolean isUpdatedSystemApp()\npublic @java.lang.Override boolean isApkInUpdatedApex()\npublic @java.lang.Override boolean isVendor()\npublic @java.lang.Override long getVersionCode()\npublic @java.lang.Override boolean hasSharedUser()\npublic @java.lang.Override boolean isApex()\nclass PackageStateImpl extends java.lang.Object implements [com.android.server.pm.pkg.PackageState]\nprivate static final int SYSTEM\nprivate static final int EXTERNAL_STORAGE\nprivate static final int PRIVILEGED\nprivate static final int OEM\nprivate static final int VENDOR\nprivate static final int PRODUCT\nprivate static final int SYSTEM_EXT\nprivate static final int REQUIRED_FOR_SYSTEM_USER\nprivate static final int ODM\nprivate static final int FORCE_QUERYABLE_OVERRIDE\nprivate static final int HIDDEN_UNTIL_INSTALLED\nprivate static final int INSTALL_PERMISSIONS_FIXED\nprivate static final int UPDATE_AVAILABLE\nprivate static final int UPDATED_SYSTEM_APP\nprivate static final int APK_IN_UPDATED_APEX\nclass Booleans extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false)")
@Deprecated
private void __metadata() {}
diff --git a/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java b/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java
index 57fbfe9..19c0886 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java
@@ -54,7 +54,6 @@
private List<String> usesLibraryFiles = emptyList();
private boolean updatedSystemApp;
- private boolean apkInApex;
private boolean apkInUpdatedApex;
@NonNull
@@ -70,6 +69,9 @@
@NonNull
private final PackageSetting mPackageSetting;
+ @Nullable
+ private String mApexModuleName;
+
public PackageStateUnserialized(@NonNull PackageSetting packageSetting) {
mPackageSetting = packageSetting;
}
@@ -138,11 +140,11 @@
}
this.updatedSystemApp = other.updatedSystemApp;
- this.apkInApex = other.apkInApex;
this.apkInUpdatedApex = other.apkInUpdatedApex;
this.lastPackageUsageTimeInMills = other.lastPackageUsageTimeInMills;
this.overrideSeInfo = other.overrideSeInfo;
this.seInfo = other.seInfo;
+ this.mApexModuleName = other.mApexModuleName;
mPackageSetting.onChanged();
}
@@ -187,12 +189,6 @@
return this;
}
- public PackageStateUnserialized setApkInApex(boolean value) {
- apkInApex = value;
- mPackageSetting.onChanged();
- return this;
- }
-
public PackageStateUnserialized setApkInUpdatedApex(boolean value) {
apkInUpdatedApex = value;
mPackageSetting.onChanged();
@@ -218,6 +214,13 @@
return this;
}
+ @NonNull
+ public PackageStateUnserialized setApexModuleName(@NonNull String value) {
+ mApexModuleName = value;
+ mPackageSetting.onChanged();
+ return this;
+ }
+
// Code below generated by codegen v1.0.23.
@@ -254,11 +257,6 @@
}
@DataClass.Generated.Member
- public boolean isApkInApex() {
- return apkInApex;
- }
-
- @DataClass.Generated.Member
public boolean isApkInUpdatedApex() {
return apkInUpdatedApex;
}
@@ -292,11 +290,16 @@
return mPackageSetting;
}
+ @DataClass.Generated.Member
+ public @Nullable String getApexModuleName() {
+ return mApexModuleName;
+ }
+
@DataClass.Generated(
- time = 1666291743725L,
+ time = 1671483772254L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java",
- inputSignatures = "private boolean hiddenUntilInstalled\nprivate @android.annotation.NonNull java.util.List<com.android.server.pm.pkg.SharedLibraryWrapper> usesLibraryInfos\nprivate @android.annotation.NonNull java.util.List<java.lang.String> usesLibraryFiles\nprivate boolean updatedSystemApp\nprivate boolean apkInApex\nprivate boolean apkInUpdatedApex\nprivate volatile @android.annotation.NonNull long[] lastPackageUsageTimeInMills\nprivate @android.annotation.Nullable java.lang.String overrideSeInfo\nprivate @android.annotation.NonNull java.lang.String seInfo\nprivate final @android.annotation.NonNull com.android.server.pm.PackageSetting mPackageSetting\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageStateUnserialized addUsesLibraryInfo(com.android.server.pm.pkg.SharedLibraryWrapper)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageStateUnserialized addUsesLibraryFile(java.lang.String)\nprivate long[] lazyInitLastPackageUsageTimeInMills()\npublic com.android.server.pm.pkg.PackageStateUnserialized setLastPackageUsageTimeInMills(int,long)\npublic long getLatestPackageUseTimeInMills()\npublic long getLatestForegroundPackageUseTimeInMills()\npublic void updateFrom(com.android.server.pm.pkg.PackageStateUnserialized)\npublic @android.annotation.NonNull java.util.List<android.content.pm.SharedLibraryInfo> getNonNativeUsesLibraryInfos()\npublic com.android.server.pm.pkg.PackageStateUnserialized setHiddenUntilInstalled(boolean)\npublic com.android.server.pm.pkg.PackageStateUnserialized setUsesLibraryInfos(java.util.List<android.content.pm.SharedLibraryInfo>)\npublic com.android.server.pm.pkg.PackageStateUnserialized setUsesLibraryFiles(java.util.List<java.lang.String>)\npublic com.android.server.pm.pkg.PackageStateUnserialized setUpdatedSystemApp(boolean)\npublic com.android.server.pm.pkg.PackageStateUnserialized setApkInApex(boolean)\npublic com.android.server.pm.pkg.PackageStateUnserialized setApkInUpdatedApex(boolean)\npublic com.android.server.pm.pkg.PackageStateUnserialized setLastPackageUsageTimeInMills(long)\npublic com.android.server.pm.pkg.PackageStateUnserialized setOverrideSeInfo(java.lang.String)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageStateUnserialized setSeInfo(java.lang.String)\nclass PackageStateUnserialized extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genSetters=true, genConstructor=false, genBuilder=false)")
+ inputSignatures = "private boolean hiddenUntilInstalled\nprivate @android.annotation.NonNull java.util.List<com.android.server.pm.pkg.SharedLibraryWrapper> usesLibraryInfos\nprivate @android.annotation.NonNull java.util.List<java.lang.String> usesLibraryFiles\nprivate boolean updatedSystemApp\nprivate boolean apkInUpdatedApex\nprivate volatile @android.annotation.NonNull long[] lastPackageUsageTimeInMills\nprivate @android.annotation.Nullable java.lang.String overrideSeInfo\nprivate @android.annotation.NonNull java.lang.String seInfo\nprivate final @android.annotation.NonNull com.android.server.pm.PackageSetting mPackageSetting\nprivate @android.annotation.Nullable java.lang.String mApexModuleName\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageStateUnserialized addUsesLibraryInfo(com.android.server.pm.pkg.SharedLibraryWrapper)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageStateUnserialized addUsesLibraryFile(java.lang.String)\nprivate long[] lazyInitLastPackageUsageTimeInMills()\npublic com.android.server.pm.pkg.PackageStateUnserialized setLastPackageUsageTimeInMills(int,long)\npublic long getLatestPackageUseTimeInMills()\npublic long getLatestForegroundPackageUseTimeInMills()\npublic void updateFrom(com.android.server.pm.pkg.PackageStateUnserialized)\npublic @android.annotation.NonNull java.util.List<android.content.pm.SharedLibraryInfo> getNonNativeUsesLibraryInfos()\npublic com.android.server.pm.pkg.PackageStateUnserialized setHiddenUntilInstalled(boolean)\npublic com.android.server.pm.pkg.PackageStateUnserialized setUsesLibraryInfos(java.util.List<android.content.pm.SharedLibraryInfo>)\npublic com.android.server.pm.pkg.PackageStateUnserialized setUsesLibraryFiles(java.util.List<java.lang.String>)\npublic com.android.server.pm.pkg.PackageStateUnserialized setUpdatedSystemApp(boolean)\npublic com.android.server.pm.pkg.PackageStateUnserialized setApkInUpdatedApex(boolean)\npublic com.android.server.pm.pkg.PackageStateUnserialized setLastPackageUsageTimeInMills(long)\npublic com.android.server.pm.pkg.PackageStateUnserialized setOverrideSeInfo(java.lang.String)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageStateUnserialized setSeInfo(java.lang.String)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageStateUnserialized setApexModuleName(java.lang.String)\nclass PackageStateUnserialized extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genSetters=true, genConstructor=false, genBuilder=false)")
@Deprecated
private void __metadata() {}
diff --git a/services/core/java/com/android/server/pm/pkg/mutate/PackageStateMutator.java b/services/core/java/com/android/server/pm/pkg/mutate/PackageStateMutator.java
index 4a8ef96..5947d47 100644
--- a/services/core/java/com/android/server/pm/pkg/mutate/PackageStateMutator.java
+++ b/services/core/java/com/android/server/pm/pkg/mutate/PackageStateMutator.java
@@ -291,6 +291,15 @@
return this;
}
+ @NonNull
+ @Override
+ public PackageStateWrite setUpdateOwner(@NonNull String updateOwnerPackageName) {
+ if (mState != null) {
+ mState.setUpdateOwnerPackage(updateOwnerPackageName);
+ }
+ return this;
+ }
+
private static class UserStateWriteWrapper implements PackageUserStateWrite {
@Nullable
diff --git a/services/core/java/com/android/server/pm/pkg/mutate/PackageStateWrite.java b/services/core/java/com/android/server/pm/pkg/mutate/PackageStateWrite.java
index dc9cd3b..c610c02 100644
--- a/services/core/java/com/android/server/pm/pkg/mutate/PackageStateWrite.java
+++ b/services/core/java/com/android/server/pm/pkg/mutate/PackageStateWrite.java
@@ -57,4 +57,7 @@
@NonNull
PackageStateWrite setInstaller(@Nullable String installerPackageName, int installerPackageUid);
+
+ @NonNull
+ PackageStateWrite setUpdateOwner(@Nullable String updateOwnerPackageName);
}
diff --git a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackage.java b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackage.java
index 69f2716..bb36758 100644
--- a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackage.java
+++ b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackage.java
@@ -387,6 +387,8 @@
ParsingPackage setLocaleConfigRes(int localeConfigRes);
+ ParsingPackage setAllowUpdateOwnership(boolean value);
+
/**
* Sets the trusted host certificates of apps that are allowed to embed activities of this
* application.
diff --git a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
index 995b9e5..31f291f 100644
--- a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
+++ b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
@@ -219,6 +219,7 @@
public static final int PARSE_DEFAULT_INSTALL_LOCATION =
PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
public static final int PARSE_DEFAULT_TARGET_SANDBOX = 1;
+ public static final boolean PARSE_DEFAULT_ALLOW_UPDATE_OWNERSHIP = true;
/**
* If set to true, we will only allow package files that exactly match the DTD. Otherwise, we
@@ -247,6 +248,9 @@
private static final String MAX_NUM_COMPONENTS_ERR_MSG =
"Total number of components has exceeded the maximum number: " + MAX_NUM_COMPONENTS;
+ /** The maximum permission name length. */
+ private static final int MAX_PERMISSION_NAME_LENGTH = 512;
+
@IntDef(flag = true, prefix = { "PARSE_" }, value = {
PARSE_CHATTY,
PARSE_COLLECT_CERTIFICATES,
@@ -883,7 +887,9 @@
.setTargetSandboxVersion(anInteger(PARSE_DEFAULT_TARGET_SANDBOX,
R.styleable.AndroidManifest_targetSandboxVersion, sa))
/* Set the global "on SD card" flag */
- .setExternalStorage((flags & PARSE_EXTERNAL_STORAGE) != 0);
+ .setExternalStorage((flags & PARSE_EXTERNAL_STORAGE) != 0)
+ .setAllowUpdateOwnership(bool(PARSE_DEFAULT_ALLOW_UPDATE_OWNERSHIP,
+ R.styleable.AndroidManifest_allowUpdateOwnership, sa));
boolean foundApp = false;
final int depth = parser.getDepth();
@@ -1260,6 +1266,11 @@
// that may change.
String name = sa.getNonResourceString(
R.styleable.AndroidManifestUsesPermission_name);
+ if (TextUtils.length(name) > MAX_PERMISSION_NAME_LENGTH) {
+ return input.error(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
+ "The name in the <uses-permission> is greater than "
+ + MAX_PERMISSION_NAME_LENGTH);
+ }
int minSdkVersion = parseMinOrMaxSdkVersion(sa,
R.styleable.AndroidManifestUsesPermission_minSdkVersion,
diff --git a/services/core/java/com/android/server/pm/resolution/ComponentResolver.java b/services/core/java/com/android/server/pm/resolution/ComponentResolver.java
index 842f685..35c42a3 100644
--- a/services/core/java/com/android/server/pm/resolution/ComponentResolver.java
+++ b/services/core/java/com/android/server/pm/resolution/ComponentResolver.java
@@ -35,6 +35,7 @@
import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
+import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.DebugUtils;
@@ -1197,6 +1198,7 @@
res.iconResourceId = info.getIcon();
res.system = res.activityInfo.applicationInfo.isSystemApp();
res.isInstantAppAvailable = userState.isInstantApp();
+ res.userHandle = UserHandle.of(userId);
return res;
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 65acdc1..b7a801a 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -661,7 +661,7 @@
dispatchMediaKeyRepeatWithWakeLock((KeyEvent)msg.obj);
break;
case MSG_DISPATCH_SHOW_RECENTS:
- showRecentApps(false);
+ showRecents();
break;
case MSG_DISPATCH_SHOW_GLOBAL_ACTIONS:
showGlobalActionsInternal();
@@ -2910,7 +2910,7 @@
break;
case KeyEvent.KEYCODE_RECENT_APPS:
if (down && repeatCount == 0) {
- showRecentApps(false /* triggeredFromAltTab */);
+ showRecents();
}
return key_consumed;
case KeyEvent.KEYCODE_APP_SWITCH:
@@ -3094,22 +3094,23 @@
}
break;
case KeyEvent.KEYCODE_TAB:
- if (down && event.isMetaPressed()) {
- if (!keyguardOn && isUserSetupComplete()) {
- showRecentApps(false);
- return key_consumed;
- }
- } else if (down && repeatCount == 0) {
- // Display task switcher for ALT-TAB.
- if (mRecentAppsHeldModifiers == 0 && !keyguardOn && isUserSetupComplete()) {
- final int shiftlessModifiers =
- event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
- if (KeyEvent.metaStateHasModifiers(
- shiftlessModifiers, KeyEvent.META_ALT_ON)) {
- mRecentAppsHeldModifiers = shiftlessModifiers;
- showRecentApps(true);
+ if (down) {
+ if (event.isMetaPressed()) {
+ if (!keyguardOn && isUserSetupComplete()) {
+ showRecents();
return key_consumed;
}
+ } else {
+ // Display task switcher for ALT-TAB.
+ if (mRecentAppsHeldModifiers == 0 && !keyguardOn && isUserSetupComplete()) {
+ final int modifiers = event.getModifiers();
+ if (KeyEvent.metaStateHasModifiers(modifiers, KeyEvent.META_ALT_ON)) {
+ mRecentAppsHeldModifiers = modifiers;
+ showRecentsFromAltTab(KeyEvent.metaStateHasModifiers(modifiers,
+ KeyEvent.META_SHIFT_ON));
+ return key_consumed;
+ }
+ }
}
}
break;
@@ -3646,11 +3647,19 @@
mHandler.obtainMessage(MSG_DISPATCH_SHOW_RECENTS).sendToTarget();
}
- private void showRecentApps(boolean triggeredFromAltTab) {
+ private void showRecents() {
mPreloadedRecentApps = false; // preloading no longer needs to be canceled
StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
if (statusbar != null) {
- statusbar.showRecentApps(triggeredFromAltTab);
+ statusbar.showRecentApps(false /* triggeredFromAltTab */, false /* forward */);
+ }
+ }
+
+ private void showRecentsFromAltTab(boolean forward) {
+ mPreloadedRecentApps = false; // preloading no longer needs to be canceled
+ StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
+ if (statusbar != null) {
+ statusbar.showRecentApps(true /* triggeredFromAltTab */, forward);
}
}
@@ -4299,9 +4308,6 @@
case KeyEvent.KEYCODE_DEMO_APP_2:
case KeyEvent.KEYCODE_DEMO_APP_3:
case KeyEvent.KEYCODE_DEMO_APP_4: {
- // TODO(b/254604589): Dispatch KeyEvent to System UI.
- sendSystemKeyToStatusBarAsync(keyCode);
-
// Just drop if keys are not intercepted for direct key.
result &= ~ACTION_PASS_TO_USER;
break;
@@ -4310,7 +4316,7 @@
case KeyEvent.KEYCODE_STYLUS_BUTTON_SECONDARY:
case KeyEvent.KEYCODE_STYLUS_BUTTON_TERTIARY:
case KeyEvent.KEYCODE_STYLUS_BUTTON_TAIL: {
- if (!mStylusButtonsDisabled) {
+ if (down && !mStylusButtonsDisabled) {
sendSystemKeyToStatusBarAsync(keyCode);
}
result &= ~ACTION_PASS_TO_USER;
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index 326d709..ed6a46f 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -737,6 +737,7 @@
}
TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
tm.notifyUserActivity();
+ mInputManagerInternal.notifyUserActivity();
mPolicy.userActivity(displayGroupId, event);
mFaceDownDetector.userActivity(event);
mScreenUndimDetector.userActivity(displayGroupId);
diff --git a/services/core/java/com/android/server/power/stats/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/power/stats/BatteryExternalStatsWorker.java
index 60dbbdd..3fcb08a 100644
--- a/services/core/java/com/android/server/power/stats/BatteryExternalStatsWorker.java
+++ b/services/core/java/com/android/server/power/stats/BatteryExternalStatsWorker.java
@@ -710,6 +710,11 @@
if (gnssChargeUC != EnergyConsumerSnapshot.UNAVAILABLE) {
mStats.updateGnssEnergyConsumerStatsLocked(gnssChargeUC, elapsedRealtime);
}
+
+ final long cameraChargeUC = energyConsumerDeltas.cameraChargeUC;
+ if (cameraChargeUC != EnergyConsumerSnapshot.UNAVAILABLE) {
+ mStats.updateCameraEnergyConsumerStatsLocked(cameraChargeUC, elapsedRealtime);
+ }
}
// Inform mStats about each applicable custom energy bucket.
if (energyConsumerDeltas != null
@@ -904,6 +909,9 @@
case EnergyConsumerType.WIFI:
buckets[EnergyConsumerStats.POWER_BUCKET_WIFI] = true;
break;
+ case EnergyConsumerType.CAMERA:
+ buckets[EnergyConsumerStats.POWER_BUCKET_CAMERA] = true;
+ break;
}
}
return buckets;
@@ -955,6 +963,9 @@
if ((flags & UPDATE_WIFI) != 0) {
addEnergyConsumerIdLocked(energyConsumerIds, EnergyConsumerType.WIFI);
}
+ if ((flags & UPDATE_CAMERA) != 0) {
+ addEnergyConsumerIdLocked(energyConsumerIds, EnergyConsumerType.CAMERA);
+ }
if (energyConsumerIds.size() == 0) {
return null;
diff --git a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
index c559436..f9482dd 100644
--- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
+++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
@@ -178,7 +178,7 @@
// TODO: remove "tcp" from network methods, since we measure total stats.
// Current on-disk Parcel version. Must be updated when the format of the parcelable changes
- public static final int VERSION = 210;
+ public static final int VERSION = 211;
// The maximum number of names wakelocks we will keep track of
// per uid; once the limit is reached, we batch the remaining wakelocks
@@ -311,6 +311,24 @@
private final RailStats mTmpRailStats = new RailStats();
/**
+ * Estimate UID modem power usage based on their estimated mobile radio active time.
+ */
+ public static final int PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME = 1;
+ /**
+ * Estimate UID modem power consumption by proportionally attributing estimated Rx and Tx
+ * power consumption individually.
+ * ModemActivityInfo must be available.
+ */
+ public static final int PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX = 2;
+ @IntDef(flag = true, prefix = "PER_UID_MODEM_MODEL_", value = {
+ PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME,
+ PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PerUidModemPowerModel {
+ }
+
+ /**
* Use a queue to delay removing UIDs from {@link KernelCpuUidUserSysTimeReader},
* {@link KernelCpuUidActiveTimeReader}, {@link KernelCpuUidClusterTimeReader},
* {@link KernelCpuUidFreqTimeReader} and from the Kernel.
@@ -649,10 +667,12 @@
int UPDATE_BT = 0x08;
int UPDATE_RPM = 0x10;
int UPDATE_DISPLAY = 0x20;
- int RESET = 0x40;
+ int UPDATE_CAMERA = 0x40;
+ int RESET = 0x80;
int UPDATE_ALL =
- UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT | UPDATE_RPM | UPDATE_DISPLAY;
+ UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT | UPDATE_RPM | UPDATE_DISPLAY
+ | UPDATE_CAMERA;
int UPDATE_ON_PROC_STATE_CHANGE = UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT;
@@ -665,6 +685,7 @@
UPDATE_BT,
UPDATE_RPM,
UPDATE_DISPLAY,
+ UPDATE_CAMERA,
UPDATE_ALL,
})
@Retention(RetentionPolicy.SOURCE)
@@ -6244,6 +6265,8 @@
}
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
.noteCameraTurnedOnLocked(elapsedRealtimeMs);
+
+ scheduleSyncExternalStatsLocked("camera-on", ExternalStatsSync.UPDATE_CAMERA);
}
@GuardedBy("this")
@@ -6259,6 +6282,8 @@
}
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
.noteCameraTurnedOffLocked(elapsedRealtimeMs);
+
+ scheduleSyncExternalStatsLocked("camera-off", ExternalStatsSync.UPDATE_CAMERA);
}
@GuardedBy("this")
@@ -6273,6 +6298,8 @@
uid.noteResetCameraLocked(elapsedRealtimeMs);
}
}
+
+ scheduleSyncExternalStatsLocked("camera-reset", ExternalStatsSync.UPDATE_CAMERA);
}
@GuardedBy("this")
@@ -7414,6 +7441,12 @@
return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_WIFI);
}
+ @GuardedBy("this")
+ @Override
+ public long getCameraEnergyConsumptionUC() {
+ return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_CAMERA);
+ }
+
/**
* Returns the consumption (in microcoulombs) that the given standard power bucket consumed.
* Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable
@@ -8427,6 +8460,12 @@
processState);
}
+ @GuardedBy("mBsi")
+ @Override
+ public long getCameraEnergyConsumptionUC() {
+ return getEnergyConsumptionUC(EnergyConsumerStats.POWER_BUCKET_CAMERA);
+ }
+
/**
* Gets the minimum of the uid's foreground activity time and its PROCESS_STATE_TOP time
* since last marked. Also sets the mark time for both these timers.
@@ -8477,6 +8516,20 @@
return gnssTimeUs;
}
+ /**
+ * Gets the uid's time spent using the camera since last marked. Also sets the mark time for
+ * the camera timer.
+ */
+ private long markCameraTimeUs(long elapsedRealtimeMs) {
+ final StopwatchTimer timer = mCameraTurnedOnTimer;
+ if (timer == null) {
+ return 0;
+ }
+ final long cameraTimeUs = timer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000);
+ timer.setMark(elapsedRealtimeMs);
+ return cameraTimeUs;
+ }
+
public StopwatchTimer createAudioTurnedOnTimerLocked() {
if (mAudioTurnedOnTimer == null) {
mAudioTurnedOnTimer = new StopwatchTimer(mBsi.mClock, Uid.this, AUDIO_TURNED_ON,
@@ -12003,8 +12056,7 @@
}
final SparseDoubleArray uidEstimatedConsumptionMah;
- if (consumedChargeUC > 0 && mMobileRadioPowerCalculator != null
- && mGlobalEnergyConsumerStats != null) {
+ if (consumedChargeUC > 0 && isMobileRadioEnergyConsumerSupportedLocked()) {
mGlobalEnergyConsumerStats.updateStandardBucket(
EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO, consumedChargeUC);
uidEstimatedConsumptionMah = new SparseDoubleArray();
@@ -12012,6 +12064,8 @@
uidEstimatedConsumptionMah = null;
}
+ RxTxConsumption rxTxConsumption = null;
+ boolean attributeWithModemActivityInfo = false;
if (deltaInfo != null) {
mHasModemReporting = true;
mModemActivity.getOrCreateIdleTimeCounter()
@@ -12057,7 +12111,11 @@
mTmpRailStats.resetCellularTotalEnergyUsed();
}
- incrementPerRatDataLocked(deltaInfo, elapsedRealtimeMs);
+ rxTxConsumption = incrementPerRatDataLocked(deltaInfo, elapsedRealtimeMs);
+
+ attributeWithModemActivityInfo = mConstants.PER_UID_MODEM_MODEL
+ == PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX
+ && rxTxConsumption != null;
}
long totalAppRadioTimeUs = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked(
elapsedRealtimeMs * 1000);
@@ -12121,12 +12179,23 @@
(totalAppRadioTimeUs * appPackets) / totalPackets;
u.noteMobileRadioActiveTimeLocked(appRadioTimeUs, elapsedRealtimeMs);
- // Distribute mobile radio charge consumption based on app radio
- // active time
if (uidEstimatedConsumptionMah != null) {
- uidEstimatedConsumptionMah.incrementValue(u.getUid(),
+ final double uidConsumptionMah;
+ if (attributeWithModemActivityInfo) {
+ // Distribute measured mobile radio charge consumption based on
+ // rx/tx packets and estimated rx/tx charge consumption.
+ uidConsumptionMah = smearModemActivityInfoRxTxConsumptionMah(
+ rxTxConsumption, entry.getRxPackets(), entry.getTxPackets(),
+ totalRxPackets, totalTxPackets);
+ } else {
+ // Distribute mobile radio charge consumption based on app radio
+ // active time
+ uidConsumptionMah =
mMobileRadioPowerCalculator.calcPowerFromRadioActiveDurationMah(
- appRadioTimeUs / 1000));
+ appRadioTimeUs / 1000);
+ }
+ uidEstimatedConsumptionMah.incrementValue(u.getUid(),
+ uidConsumptionMah);
}
// Remove this app from the totals, so that we don't lose any time
@@ -12164,54 +12233,95 @@
mMobileRadioActiveUnknownCount.addCountLocked(1);
}
-
// Update the EnergyConsumerStats information.
if (uidEstimatedConsumptionMah != null) {
double totalEstimatedConsumptionMah = 0.0;
-
- // Estimate total active radio power consumption since last mark.
- final long totalRadioTimeMs = mMobileRadioActiveTimer.getTimeSinceMarkLocked(
- elapsedRealtimeMs * 1000) / 1000;
- mMobileRadioActiveTimer.setMark(elapsedRealtimeMs);
- totalEstimatedConsumptionMah +=
- mMobileRadioPowerCalculator.calcPowerFromRadioActiveDurationMah(
- totalRadioTimeMs);
-
- // Estimate idle power consumption at each signal strength level
- final int numSignalStrengthLevels = mPhoneSignalStrengthsTimer.length;
- for (int strengthLevel = 0; strengthLevel < numSignalStrengthLevels;
- strengthLevel++) {
- final long strengthLevelDurationMs =
- mPhoneSignalStrengthsTimer[strengthLevel].getTimeSinceMarkLocked(
+ if (attributeWithModemActivityInfo) {
+ // Estimate inactive modem power consumption and combine with previously
+ // estimated active power consumption for an estimate of total modem
+ // power consumption.
+ final long sleepTimeMs = deltaInfo.getSleepTimeMillis();
+ final long idleTimeMs = deltaInfo.getIdleTimeMillis();
+ final double inactiveConsumptionMah =
+ mMobileRadioPowerCalculator.calcInactiveStatePowerMah(sleepTimeMs,
+ idleTimeMs);
+ totalEstimatedConsumptionMah += inactiveConsumptionMah;
+ totalEstimatedConsumptionMah += rxTxConsumption.rxConsumptionMah;
+ totalEstimatedConsumptionMah += rxTxConsumption.txConsumptionMah;
+ } else {
+ // Estimate total active radio power consumption since last mark.
+ final long totalRadioTimeMs =
+ mMobileRadioActiveTimer.getTimeSinceMarkLocked(
elapsedRealtimeMs * 1000) / 1000;
- mPhoneSignalStrengthsTimer[strengthLevel].setMark(elapsedRealtimeMs);
-
+ mMobileRadioActiveTimer.setMark(elapsedRealtimeMs);
totalEstimatedConsumptionMah +=
- mMobileRadioPowerCalculator.calcIdlePowerAtSignalStrengthMah(
- strengthLevelDurationMs, strengthLevel);
+ mMobileRadioPowerCalculator.calcPowerFromRadioActiveDurationMah(
+ totalRadioTimeMs);
+
+ // Estimate idle power consumption at each signal strength level
+ final int numSignalStrengthLevels = mPhoneSignalStrengthsTimer.length;
+ for (int lvl = 0; lvl < numSignalStrengthLevels; lvl++) {
+ final long strengthLevelDurationMs =
+ mPhoneSignalStrengthsTimer[lvl].getTimeSinceMarkLocked(
+ elapsedRealtimeMs * 1000) / 1000;
+ mPhoneSignalStrengthsTimer[lvl].setMark(elapsedRealtimeMs);
+
+ totalEstimatedConsumptionMah +=
+ mMobileRadioPowerCalculator.calcIdlePowerAtSignalStrengthMah(
+ strengthLevelDurationMs, lvl);
+ }
+
+ // Estimate total active radio power consumption since last mark.
+ final long scanTimeMs = mPhoneSignalScanningTimer.getTimeSinceMarkLocked(
+ elapsedRealtimeMs * 1000) / 1000;
+ mPhoneSignalScanningTimer.setMark(elapsedRealtimeMs);
+ totalEstimatedConsumptionMah +=
+ mMobileRadioPowerCalculator.calcScanTimePowerMah(scanTimeMs);
}
-
- // Estimate total active radio power consumption since last mark.
- final long scanTimeMs = mPhoneSignalScanningTimer.getTimeSinceMarkLocked(
- elapsedRealtimeMs * 1000) / 1000;
- mPhoneSignalScanningTimer.setMark(elapsedRealtimeMs);
- totalEstimatedConsumptionMah +=
- mMobileRadioPowerCalculator.calcScanTimePowerMah(scanTimeMs);
-
distributeEnergyToUidsLocked(EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO,
consumedChargeUC, uidEstimatedConsumptionMah,
totalEstimatedConsumptionMah, elapsedRealtimeMs);
}
+ }
+ }
+ }
- delta = null;
+ private static class RxTxConsumption {
+ public final double rxConsumptionMah;
+ public final long rxDurationMs;
+ public final double txConsumptionMah;
+ public final long txDurationMs;
+
+ /**
+ * Represents the ratio between time spent transmitting and the total active time.
+ */
+ public final double txToTotalRatio;
+
+ RxTxConsumption(double rxMah, long rxMs, double txMah, long txMs) {
+ rxConsumptionMah = rxMah;
+ rxDurationMs = rxMs;
+ txConsumptionMah = txMah;
+ txDurationMs = txMs;
+
+ final long activeDurationMs = txDurationMs + rxDurationMs;
+ if (activeDurationMs == 0) {
+ txToTotalRatio = 0.0;
+ } else {
+ txToTotalRatio = ((double) txDurationMs) / activeDurationMs;
}
}
}
@GuardedBy("this")
- private void incrementPerRatDataLocked(ModemActivityInfo deltaInfo, long elapsedRealtimeMs) {
- final int infoSize = deltaInfo.getSpecificInfoLength();
+ @Nullable
+ private RxTxConsumption incrementPerRatDataLocked(ModemActivityInfo deltaInfo,
+ long elapsedRealtimeMs) {
+ double rxConsumptionMah = 0.0;
+ long rxDurationMs = 0;
+ double txConsumptionMah = 0.0;
+ long txDurationMs = 0;
+ final int infoSize = deltaInfo.getSpecificInfoLength();
if (infoSize == 1 && deltaInfo.getSpecificInfoRat(0)
== AccessNetworkConstants.AccessNetworkType.UNKNOWN
&& deltaInfo.getSpecificInfoFrequencyRange(0)
@@ -12261,6 +12371,16 @@
+ (totalLvlDurationMs / 2)) / totalLvlDurationMs;
ratStats.incrementTxDuration(freq, level, proportionalTxDurationMs);
frequencyDurationMs += durationMs;
+
+ if (isMobileRadioEnergyConsumerSupportedLocked()) {
+ // Accumulate the power cost of time spent transmitting in a
+ // particular state.
+ final double txStatePowerConsumptionMah =
+ mMobileRadioPowerCalculator.calcTxStatePowerMah(rat, freq,
+ level, proportionalTxDurationMs);
+ txConsumptionMah += txStatePowerConsumptionMah;
+ txDurationMs += proportionalTxDurationMs;
+ }
}
final long totalRxDuration = deltaInfo.getReceiveTimeMillis();
// Smear HAL provided Rx power duration based on active modem
@@ -12270,6 +12390,16 @@
(frequencyDurationMs * totalRxDuration + (totalActiveTimeMs
/ 2)) / totalActiveTimeMs;
ratStats.incrementRxDuration(freq, proportionalRxDurationMs);
+
+ if (isMobileRadioEnergyConsumerSupportedLocked()) {
+ // Accumulate the power cost of time spent receiving in a particular
+ // state.
+ final double rxStatePowerConsumptionMah =
+ mMobileRadioPowerCalculator.calcRxStatePowerMah(rat, freq,
+ proportionalRxDurationMs);
+ rxConsumptionMah += rxStatePowerConsumptionMah;
+ rxDurationMs += proportionalRxDurationMs;
+ }
}
}
@@ -12289,9 +12419,28 @@
final int[] txTimesMs = deltaInfo.getTransmitTimeMillis(rat, freq);
ratStats.incrementRxDuration(freq, rxTimeMs);
+ if (isMobileRadioEnergyConsumerSupportedLocked()) {
+ // Accumulate the power cost of time spent receiving in a particular state.
+ final double rxStatePowerConsumptionMah =
+ mMobileRadioPowerCalculator.calcRxStatePowerMah(ratBucket, freq,
+ rxTimeMs);
+ rxConsumptionMah += rxStatePowerConsumptionMah;
+ rxDurationMs += rxTimeMs;
+ }
+
final int numTxLvl = txTimesMs.length;
for (int lvl = 0; lvl < numTxLvl; lvl++) {
- ratStats.incrementTxDuration(freq, lvl, txTimesMs[lvl]);
+ final long txTimeMs = txTimesMs[lvl];
+ ratStats.incrementTxDuration(freq, lvl, txTimeMs);
+ if (isMobileRadioEnergyConsumerSupportedLocked()) {
+ // Accumulate the power cost of time spent transmitting in a particular
+ // state.
+ final double txStatePowerConsumptionMah =
+ mMobileRadioPowerCalculator.calcTxStatePowerMah(ratBucket, freq,
+ lvl, txTimeMs);
+ txConsumptionMah += txStatePowerConsumptionMah;
+ txDurationMs += txTimeMs;
+ }
}
}
}
@@ -12301,6 +12450,45 @@
if (ratStats == null) continue;
ratStats.setMark(elapsedRealtimeMs);
}
+
+ if (isMobileRadioEnergyConsumerSupportedLocked()) {
+ return new RxTxConsumption(rxConsumptionMah, rxDurationMs, txConsumptionMah,
+ txDurationMs);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Smear modem Rx/Tx power consumption calculated from {@link ModemActivityInfo} using Rx/Tx
+ * packets.
+ *
+ * @return the combine Rx/Tx smeared power consumption in milliamp-hours.
+ */
+ private double smearModemActivityInfoRxTxConsumptionMah(RxTxConsumption rxTxConsumption,
+ long rxPackets, long txPackets, long totalRxPackets, long totalTxPackets) {
+ // Distribute measured mobile radio charge consumption based on
+ // rx/tx packets and estimated rx/tx charge consumption.
+ double consumptionMah = 0.0;
+ if (totalRxPackets != 0) {
+ // Proportionally distribute receive battery consumption.
+ consumptionMah += rxTxConsumption.rxConsumptionMah * rxPackets
+ / totalRxPackets;
+ }
+ if (totalTxPackets != 0 || (totalRxPackets != 0 && rxTxConsumption.txToTotalRatio != 0.0)) {
+ // ModemActivityInfo Tx time represents time spent both transmitting and receiving.
+ // There is currently no way to distinguish how many Rx packets were received during
+ // Rx time vs Tx time.
+ // Assumption: The number of packets received while transmitting is proportional
+ // to the time spent transmitting over total active time.
+ final double totalPacketsDuringTxTime =
+ totalTxPackets + rxTxConsumption.txToTotalRatio * totalRxPackets;
+ final double packetsDuringTxTime =
+ txPackets + rxTxConsumption.txToTotalRatio * rxPackets;
+ consumptionMah += rxTxConsumption.txConsumptionMah * packetsDuringTxTime
+ / totalPacketsDuringTxTime;
+ }
+ return consumptionMah;
}
/**
@@ -12902,6 +13090,53 @@
}
/**
+ * Accumulate camera charge consumption and distribute it to the correct state and the apps.
+ *
+ * @param chargeUC amount of charge (microcoulombs) used by the camera since this was last
+ * called.
+ */
+ @GuardedBy("this")
+ public void updateCameraEnergyConsumerStatsLocked(long chargeUC, long elapsedRealtimeMs) {
+ if (DEBUG_ENERGY) Slog.d(TAG, "Updating camera stats: " + chargeUC);
+ if (mGlobalEnergyConsumerStats == null) {
+ return;
+ }
+
+ if (!mOnBatteryInternal || chargeUC <= 0) {
+ // There's nothing further to update.
+ return;
+ }
+
+ if (mIgnoreNextExternalStats) {
+ // Although under ordinary resets we won't get here, and typically a new sync will
+ // happen right after the reset, strictly speaking we need to set all mark times to now.
+ final int uidStatsSize = mUidStats.size();
+ for (int i = 0; i < uidStatsSize; i++) {
+ final Uid uid = mUidStats.valueAt(i);
+ uid.markCameraTimeUs(elapsedRealtimeMs);
+ }
+ return;
+ }
+
+ mGlobalEnergyConsumerStats.updateStandardBucket(
+ EnergyConsumerStats.POWER_BUCKET_CAMERA, chargeUC);
+
+ // Collect the per uid time since mark so that we can normalize power.
+ final SparseDoubleArray cameraTimeUsArray = new SparseDoubleArray();
+
+ // Note: Iterating over all UIDs may be suboptimal.
+ final int uidStatsSize = mUidStats.size();
+ for (int i = 0; i < uidStatsSize; i++) {
+ final Uid uid = mUidStats.valueAt(i);
+ final long cameraTimeUs = uid.markCameraTimeUs(elapsedRealtimeMs);
+ if (cameraTimeUs == 0) continue;
+ cameraTimeUsArray.put(uid.getUid(), (double) cameraTimeUs);
+ }
+ distributeEnergyToUidsLocked(EnergyConsumerStats.POWER_BUCKET_CAMERA, chargeUC,
+ cameraTimeUsArray, 0, elapsedRealtimeMs);
+ }
+
+ /**
* Accumulate Custom power bucket charge, globally and for each app.
*
* @param totalChargeUC charge (microcoulombs) used for this bucket since this was last called.
@@ -14762,6 +14997,13 @@
}
}
+ @GuardedBy("this")
+ private boolean isMobileRadioEnergyConsumerSupportedLocked() {
+ if (mGlobalEnergyConsumerStats == null) return false;
+ return mGlobalEnergyConsumerStats.isStandardBucketSupported(
+ EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO);
+ }
+
@NonNull
private static String[] getBatteryConsumerProcessStateNames() {
String[] procStateNames = new String[BatteryConsumer.PROCESS_STATE_COUNT];
@@ -14797,6 +15039,40 @@
"battery_charged_delay_ms";
public static final String KEY_RECORD_USAGE_HISTORY =
"record_usage_history";
+ public static final String KEY_PER_UID_MODEM_POWER_MODEL =
+ "per_uid_modem_power_model";
+
+ public static final String PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME_NAME =
+ "mobile_radio_active_time";
+ public static final String PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX_NAME =
+ "modem_activity_info_rx_tx";
+
+ /** Convert {@link PerUidModemPowerModel} to string */
+ public String getPerUidModemModelName(@PerUidModemPowerModel int model) {
+ switch(model) {
+ case PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME:
+ return PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME_NAME;
+ case PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX:
+ return PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX_NAME;
+ default:
+ Slog.w(TAG, "Unexpected per uid modem model (" + model + ")");
+ return "unknown_" + model;
+ }
+ }
+
+ /** Convert string to {@link PerUidModemPowerModel} */
+ @PerUidModemPowerModel
+ public int getPerUidModemModel(String name) {
+ switch(name) {
+ case PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME_NAME:
+ return PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME;
+ case PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX_NAME:
+ return PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX;
+ default:
+ Slog.w(TAG, "Unexpected per uid modem model name (" + name + ")");
+ return DEFAULT_PER_UID_MODEM_MODEL;
+ }
+ }
private static final boolean DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME = true;
private static final long DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME = 1_000;
@@ -14810,6 +15086,9 @@
private static final int DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB = 64; /*Kilo Bytes*/
private static final int DEFAULT_BATTERY_CHARGED_DELAY_MS = 900000; /* 15 min */
private static final boolean DEFAULT_RECORD_USAGE_HISTORY = false;
+ @PerUidModemPowerModel
+ private static final int DEFAULT_PER_UID_MODEM_MODEL =
+ PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX;
public boolean TRACK_CPU_ACTIVE_CLUSTER_TIME = DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME;
/* Do not set default value for KERNEL_UID_READERS_THROTTLE_TIME. Need to trigger an
@@ -14826,6 +15105,7 @@
public int MAX_HISTORY_BUFFER; /*Bytes*/
public int BATTERY_CHARGED_DELAY_MS = DEFAULT_BATTERY_CHARGED_DELAY_MS;
public boolean RECORD_USAGE_HISTORY = DEFAULT_RECORD_USAGE_HISTORY;
+ public int PER_UID_MODEM_MODEL = DEFAULT_PER_UID_MODEM_MODEL;
private ContentResolver mResolver;
private final KeyValueListParser mParser = new KeyValueListParser(',');
@@ -14903,6 +15183,9 @@
* 1024;
RECORD_USAGE_HISTORY = mParser.getBoolean(
KEY_RECORD_USAGE_HISTORY, DEFAULT_RECORD_USAGE_HISTORY);
+ final String perUidModemModel = mParser.getString(KEY_PER_UID_MODEM_POWER_MODEL,
+ "");
+ PER_UID_MODEM_MODEL = getPerUidModemModel(perUidModemModel);
updateBatteryChargedDelayMsLocked();
@@ -14971,6 +15254,8 @@
pw.println(BATTERY_CHARGED_DELAY_MS);
pw.print(KEY_RECORD_USAGE_HISTORY); pw.print("=");
pw.println(RECORD_USAGE_HISTORY);
+ pw.print(KEY_PER_UID_MODEM_POWER_MODEL); pw.print("=");
+ pw.println(getPerUidModemModelName(PER_UID_MODEM_MODEL));
}
}
diff --git a/services/core/java/com/android/server/power/stats/CameraPowerCalculator.java b/services/core/java/com/android/server/power/stats/CameraPowerCalculator.java
index 16892034..89991bf 100644
--- a/services/core/java/com/android/server/power/stats/CameraPowerCalculator.java
+++ b/services/core/java/com/android/server/power/stats/CameraPowerCalculator.java
@@ -48,27 +48,44 @@
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
super.calculate(builder, batteryStats, rawRealtimeUs, rawUptimeUs, query);
- final long durationMs = batteryStats.getCameraOnTime(rawRealtimeUs,
- BatteryStats.STATS_SINCE_CHARGED) / 1000;
- final double powerMah = mPowerEstimator.calculatePower(durationMs);
+ long consumptionUc = batteryStats.getCameraEnergyConsumptionUC();
+ int powerModel = getPowerModel(consumptionUc, query);
+ long durationMs =
+ batteryStats.getCameraOnTime(
+ rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED) / 1000;
+ double powerMah;
+ if (powerModel == BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION) {
+ powerMah = uCtoMah(consumptionUc);
+ } else {
+ powerMah = mPowerEstimator.calculatePower(durationMs);
+ }
+
builder.getAggregateBatteryConsumerBuilder(
- BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE)
+ BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE)
.setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_CAMERA, durationMs)
- .setConsumedPower(BatteryConsumer.POWER_COMPONENT_CAMERA, powerMah);
+ .setConsumedPower(BatteryConsumer.POWER_COMPONENT_CAMERA, powerMah, powerModel);
builder.getAggregateBatteryConsumerBuilder(
- BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS)
+ BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS)
.setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_CAMERA, durationMs)
- .setConsumedPower(BatteryConsumer.POWER_COMPONENT_CAMERA, powerMah);
+ .setConsumedPower(BatteryConsumer.POWER_COMPONENT_CAMERA, powerMah, powerModel);
}
@Override
protected void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
- final long durationMs =
+ long consumptionUc = app.getBatteryStatsUid().getCameraEnergyConsumptionUC();
+ int powerModel = getPowerModel(consumptionUc, query);
+ long durationMs =
mPowerEstimator.calculateDuration(u.getCameraTurnedOnTimer(), rawRealtimeUs,
BatteryStats.STATS_SINCE_CHARGED);
- final double powerMah = mPowerEstimator.calculatePower(durationMs);
+ double powerMah;
+ if (powerModel == BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION) {
+ powerMah = uCtoMah(consumptionUc);
+ } else {
+ powerMah = mPowerEstimator.calculatePower(durationMs);
+ }
+
app.setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_CAMERA, durationMs)
- .setConsumedPower(BatteryConsumer.POWER_COMPONENT_CAMERA, powerMah);
+ .setConsumedPower(BatteryConsumer.POWER_COMPONENT_CAMERA, powerMah, powerModel);
}
}
diff --git a/services/core/java/com/android/server/power/stats/EnergyConsumerSnapshot.java b/services/core/java/com/android/server/power/stats/EnergyConsumerSnapshot.java
index 18595ca..939a08b 100644
--- a/services/core/java/com/android/server/power/stats/EnergyConsumerSnapshot.java
+++ b/services/core/java/com/android/server/power/stats/EnergyConsumerSnapshot.java
@@ -123,6 +123,9 @@
/** The chargeUC for {@link EnergyConsumerType#WIFI}. */
public long wifiChargeUC = UNAVAILABLE;
+ /** The chargeUC for {@link EnergyConsumerType#CAMERA}. */
+ public long cameraChargeUC = UNAVAILABLE;
+
/** Map of {@link EnergyConsumerType#OTHER} ordinals to their total chargeUC. */
public @Nullable long[] otherTotalChargeUC = null;
@@ -256,6 +259,10 @@
output.wifiChargeUC = deltaChargeUC;
break;
+ case EnergyConsumerType.CAMERA:
+ output.cameraChargeUC = deltaChargeUC;
+ break;
+
case EnergyConsumerType.OTHER:
if (output.otherTotalChargeUC == null) {
output.otherTotalChargeUC = new long[mNumOtherOrdinals];
@@ -458,6 +465,9 @@
case EnergyConsumerType.WIFI:
chargeUC[i] = delta.wifiChargeUC;
break;
+ case EnergyConsumerType.CAMERA:
+ chargeUC[i] = delta.cameraChargeUC;
+ break;
case EnergyConsumerType.OTHER:
if (delta.otherTotalChargeUC != null) {
chargeUC[i] = delta.otherTotalChargeUC[energyConsumer.ordinal];
diff --git a/services/core/java/com/android/server/power/stats/MobileRadioPowerCalculator.java b/services/core/java/com/android/server/power/stats/MobileRadioPowerCalculator.java
index 4608e9a..3226260 100644
--- a/services/core/java/com/android/server/power/stats/MobileRadioPowerCalculator.java
+++ b/services/core/java/com/android/server/power/stats/MobileRadioPowerCalculator.java
@@ -270,25 +270,28 @@
// Calculate the inactive modem power consumption.
final BatteryStats.ControllerActivityCounter modemActivity =
batteryStats.getModemControllerActivity();
- if (modemActivity != null && (mSleepPowerEstimator != null
- || mIdlePowerEstimator != null)) {
+ double inactivePowerMah = Double.NaN;
+ if (modemActivity != null) {
final long sleepDurationMs = modemActivity.getSleepTimeCounter().getCountLocked(
BatteryStats.STATS_SINCE_CHARGED);
- total.remainingPowerMah += mSleepPowerEstimator.calculatePower(sleepDurationMs);
final long idleDurationMs = modemActivity.getIdleTimeCounter().getCountLocked(
BatteryStats.STATS_SINCE_CHARGED);
- total.remainingPowerMah += mIdlePowerEstimator.calculatePower(idleDurationMs);
- } else {
+ inactivePowerMah = calcInactiveStatePowerMah(sleepDurationMs, idleDurationMs);
+ }
+ if (Double.isNaN(inactivePowerMah)) {
// Modem activity counters unavailable. Use legacy calculations for inactive usage.
final long scanningTimeMs = batteryStats.getPhoneSignalScanningTime(rawRealtimeUs,
BatteryStats.STATS_SINCE_CHARGED) / 1000;
- total.remainingPowerMah += calcScanTimePowerMah(scanningTimeMs);
+ inactivePowerMah = calcScanTimePowerMah(scanningTimeMs);
for (int i = 0; i < NUM_SIGNAL_STRENGTH_LEVELS; i++) {
long strengthTimeMs = batteryStats.getPhoneSignalStrengthTime(i, rawRealtimeUs,
BatteryStats.STATS_SINCE_CHARGED) / 1000;
- total.remainingPowerMah += calcIdlePowerAtSignalStrengthMah(strengthTimeMs, i);
+ inactivePowerMah += calcIdlePowerAtSignalStrengthMah(strengthTimeMs, i);
}
}
+ if (!Double.isNaN(inactivePowerMah)) {
+ total.remainingPowerMah += inactivePowerMah;
+ }
}
@@ -509,6 +512,22 @@
}
/**
+ * Calculates active transmit radio power consumption (in milliamp-hours) from the given state's
+ * duration.
+ */
+ public double calcInactiveStatePowerMah(long sleepDurationMs, long idleDurationMs) {
+ if (mSleepPowerEstimator == null || mIdlePowerEstimator == null) return Double.NaN;
+ final double sleepConsumptionMah = mSleepPowerEstimator.calculatePower(sleepDurationMs);
+ final double idleConsumptionMah = mIdlePowerEstimator.calculatePower(idleDurationMs);
+ if (DEBUG) {
+ Log.d(TAG, "Calculated sleep consumption " + sleepConsumptionMah
+ + " mAH from a duration of " + sleepDurationMs + " ms and idle consumption "
+ + idleConsumptionMah + " mAH from a duration of " + idleDurationMs);
+ }
+ return sleepConsumptionMah + idleConsumptionMah;
+ }
+
+ /**
* Calculates active radio power consumption (in milliamp-hours) from active radio duration.
*/
public double calcPowerFromRadioActiveDurationMah(long radioActiveDurationMs) {
diff --git a/services/core/java/com/android/server/resources/ResourcesManagerService.java b/services/core/java/com/android/server/resources/ResourcesManagerService.java
index eec3a02..94aa518 100644
--- a/services/core/java/com/android/server/resources/ResourcesManagerService.java
+++ b/services/core/java/com/android/server/resources/ResourcesManagerService.java
@@ -74,8 +74,8 @@
@Override
protected void dump(@NonNull FileDescriptor fd,
@NonNull PrintWriter pw, @Nullable String[] args) {
- try {
- mActivityManagerService.dumpAllResources(ParcelFileDescriptor.dup(fd), pw);
+ try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(fd)) {
+ mActivityManagerService.dumpAllResources(pfd, pw);
} catch (Exception e) {
pw.println("Exception while trying to dump all resources: " + e.getMessage());
e.printStackTrace(pw);
diff --git a/services/core/java/com/android/server/resources/ResourcesManagerShellCommand.java b/services/core/java/com/android/server/resources/ResourcesManagerShellCommand.java
index 7d8336a..a75d110 100644
--- a/services/core/java/com/android/server/resources/ResourcesManagerShellCommand.java
+++ b/services/core/java/com/android/server/resources/ResourcesManagerShellCommand.java
@@ -62,13 +62,12 @@
private int dumpResources() throws RemoteException {
String processId = getNextArgRequired();
- try {
+ try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(getOutFileDescriptor())) {
ConditionVariable lock = new ConditionVariable();
RemoteCallback
finishCallback = new RemoteCallback(result -> lock.open(), null);
- if (!mInterface.dumpResources(processId,
- ParcelFileDescriptor.dup(getOutFileDescriptor()), finishCallback)) {
+ if (!mInterface.dumpResources(processId, pfd, finishCallback)) {
getErrPrintWriter().println("RESOURCES DUMP FAILED on process " + processId);
return -1;
}
diff --git a/services/core/java/com/android/server/security/rkp/RemoteProvisioningRegistration.java b/services/core/java/com/android/server/security/rkp/RemoteProvisioningRegistration.java
index 868f34b..0e92709 100644
--- a/services/core/java/com/android/server/security/rkp/RemoteProvisioningRegistration.java
+++ b/services/core/java/com/android/server/security/rkp/RemoteProvisioningRegistration.java
@@ -21,10 +21,12 @@
import android.os.OutcomeReceiver;
import android.security.rkp.IGetKeyCallback;
import android.security.rkp.IRegistration;
+import android.security.rkp.IStoreUpgradedKeyCallback;
import android.security.rkp.service.RegistrationProxy;
import android.security.rkp.service.RemotelyProvisionedKey;
import android.util.Log;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
@@ -36,8 +38,10 @@
*/
final class RemoteProvisioningRegistration extends IRegistration.Stub {
static final String TAG = RemoteProvisioningService.TAG;
- private final ConcurrentHashMap<IGetKeyCallback, CancellationSignal> mOperations =
+ private final ConcurrentHashMap<IGetKeyCallback, CancellationSignal> mGetKeyOperations =
new ConcurrentHashMap<>();
+ private final Set<IStoreUpgradedKeyCallback> mStoreUpgradedKeyOperations =
+ ConcurrentHashMap.newKeySet();
private final RegistrationProxy mRegistration;
private final Executor mExecutor;
@@ -49,7 +53,7 @@
@Override
public void onResult(RemotelyProvisionedKey result) {
- mOperations.remove(mCallback);
+ mGetKeyOperations.remove(mCallback);
Log.i(TAG, "Successfully fetched key for client " + mCallback.hashCode());
android.security.rkp.RemotelyProvisionedKey parcelable =
new android.security.rkp.RemotelyProvisionedKey();
@@ -60,7 +64,7 @@
@Override
public void onError(Exception e) {
- mOperations.remove(mCallback);
+ mGetKeyOperations.remove(mCallback);
if (e instanceof OperationCanceledException) {
Log.i(TAG, "Operation cancelled for client " + mCallback.hashCode());
wrapCallback(mCallback::onCancel);
@@ -79,7 +83,7 @@
@Override
public void getKey(int keyId, IGetKeyCallback callback) {
CancellationSignal cancellationSignal = new CancellationSignal();
- if (mOperations.putIfAbsent(callback, cancellationSignal) != null) {
+ if (mGetKeyOperations.putIfAbsent(callback, cancellationSignal) != null) {
Log.e(TAG, "Client can only request one call at a time " + callback.hashCode());
throw new IllegalArgumentException(
"Callback is already associated with an existing operation: "
@@ -92,14 +96,14 @@
new GetKeyReceiver(callback));
} catch (Exception e) {
Log.e(TAG, "getKeyAsync threw an exception for client " + callback.hashCode(), e);
- mOperations.remove(callback);
+ mGetKeyOperations.remove(callback);
wrapCallback(() -> callback.onError(e.getMessage()));
}
}
@Override
public void cancelGetKey(IGetKeyCallback callback) {
- CancellationSignal cancellationSignal = mOperations.remove(callback);
+ CancellationSignal cancellationSignal = mGetKeyOperations.remove(callback);
if (cancellationSignal == null) {
throw new IllegalArgumentException(
"Invalid client in cancelGetKey: " + callback.hashCode());
@@ -110,9 +114,35 @@
}
@Override
- public void storeUpgradedKey(byte[] oldKeyBlob, byte[] newKeyBlob) {
- // TODO(b/262748535)
- Log.e(TAG, "RegistrationBinder.storeUpgradedKey NOT YET IMPLEMENTED");
+ public void storeUpgradedKeyAsync(byte[] oldKeyBlob, byte[] newKeyBlob,
+ IStoreUpgradedKeyCallback callback) {
+ if (!mStoreUpgradedKeyOperations.add(callback)) {
+ throw new IllegalArgumentException(
+ "Callback is already associated with an existing operation: "
+ + callback.hashCode());
+ }
+
+ try {
+ mRegistration.storeUpgradedKeyAsync(oldKeyBlob, newKeyBlob, mExecutor,
+ new OutcomeReceiver<>() {
+ @Override
+ public void onResult(Void result) {
+ mStoreUpgradedKeyOperations.remove(callback);
+ wrapCallback(callback::onSuccess);
+ }
+
+ @Override
+ public void onError(Exception e) {
+ mStoreUpgradedKeyOperations.remove(callback);
+ wrapCallback(() -> callback.onError(e.getMessage()));
+ }
+ });
+ } catch (Exception e) {
+ Log.e(TAG, "storeUpgradedKeyAsync threw an exception for client "
+ + callback.hashCode(), e);
+ mStoreUpgradedKeyOperations.remove(callback);
+ wrapCallback(() -> callback.onError(e.getMessage()));
+ }
}
interface CallbackRunner {
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index 392fda9..0fd6d9b 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -39,7 +39,7 @@
void cancelPreloadRecentApps();
- void showRecentApps(boolean triggeredFromAltTab);
+ void showRecentApps(boolean triggeredFromAltTab, boolean forward);
void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey);
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 8d71d9c..97ca8df 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -454,10 +454,10 @@
}
@Override
- public void showRecentApps(boolean triggeredFromAltTab) {
+ public void showRecentApps(boolean triggeredFromAltTab, boolean forward) {
if (mBar != null) {
try {
- mBar.showRecentApps(triggeredFromAltTab);
+ mBar.showRecentApps(triggeredFromAltTab, forward);
} catch (RemoteException ex) {}
}
}
diff --git a/services/core/java/com/android/server/testharness/TestHarnessModeService.java b/services/core/java/com/android/server/testharness/TestHarnessModeService.java
index 452bdf4..bfe34049e 100644
--- a/services/core/java/com/android/server/testharness/TestHarnessModeService.java
+++ b/services/core/java/com/android/server/testharness/TestHarnessModeService.java
@@ -17,13 +17,13 @@
package com.android.server.testharness;
import android.annotation.Nullable;
+import android.annotation.UserIdInt;
import android.app.KeyguardManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.UserInfo;
import android.debug.AdbManagerInternal;
import android.location.LocationManager;
import android.os.BatteryManager;
@@ -34,7 +34,6 @@
import android.os.ShellCommand;
import android.os.SystemProperties;
import android.os.UserHandle;
-import android.os.UserManager;
import android.provider.Settings;
import android.util.Slog;
@@ -44,6 +43,7 @@
import com.android.server.LocalServices;
import com.android.server.PersistentDataBlockManagerInternal;
import com.android.server.SystemService;
+import com.android.server.pm.UserManagerInternal;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -117,9 +117,9 @@
}
private void disableLockScreen() {
- UserInfo userInfo = getPrimaryUser();
+ int mainUserId = getMainUserId();
LockPatternUtils utils = new LockPatternUtils(getContext());
- utils.setLockScreenDisabled(true, userInfo.id);
+ utils.setLockScreenDisabled(true, mainUserId);
}
private void completeTestHarnessModeSetup() {
@@ -193,17 +193,24 @@
}
private void configureUser() {
- UserInfo primaryUser = getPrimaryUser();
+ int mainUserId = getMainUserId();
- ContentResolver.setMasterSyncAutomaticallyAsUser(false, primaryUser.id);
+ ContentResolver.setMasterSyncAutomaticallyAsUser(false, mainUserId);
LocationManager locationManager = getContext().getSystemService(LocationManager.class);
- locationManager.setLocationEnabledForUser(true, primaryUser.getUserHandle());
+ locationManager.setLocationEnabledForUser(true, UserHandle.of(mainUserId));
}
- private UserInfo getPrimaryUser() {
- UserManager userManager = UserManager.get(getContext());
- return userManager.getPrimaryUser();
+ private @UserIdInt int getMainUserId() {
+ UserManagerInternal umi = LocalServices.getService(UserManagerInternal.class);
+ int mainUserId = umi.getMainUserId();
+ if (mainUserId >= 0) {
+ return mainUserId;
+ } else {
+ // If there is no MainUser, fall back to the historical usage of user 0.
+ Slog.w(TAG, "No MainUser exists; using user 0 instead");
+ return UserHandle.USER_SYSTEM;
+ }
}
private void writeBytesToFile(byte[] keys, Path adbKeys) {
@@ -318,7 +325,7 @@
private boolean isDeviceSecure() {
KeyguardManager keyguardManager = getContext().getSystemService(KeyguardManager.class);
- return keyguardManager.isDeviceSecure(getPrimaryUser().id);
+ return keyguardManager.isDeviceSecure(getMainUserId());
}
private int handleEnable() {
diff --git a/services/core/java/com/android/server/timedetector/NetworkTimeUpdateService.java b/services/core/java/com/android/server/timedetector/NetworkTimeUpdateService.java
index 41824de..0809297 100644
--- a/services/core/java/com/android/server/timedetector/NetworkTimeUpdateService.java
+++ b/services/core/java/com/android/server/timedetector/NetworkTimeUpdateService.java
@@ -16,6 +16,7 @@
package com.android.server.timedetector;
+import android.annotation.ElapsedRealtimeLong;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -39,12 +40,14 @@
import android.os.ShellCallback;
import android.os.SystemClock;
import android.provider.Settings;
+import android.util.IndentingPrintWriter;
import android.util.LocalLog;
import android.util.Log;
import android.util.NtpTrustedTime;
import android.util.NtpTrustedTime.TimeResult;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.DumpUtils;
import com.android.server.LocalServices;
@@ -52,12 +55,17 @@
import java.io.PrintWriter;
import java.time.Duration;
import java.util.Objects;
+import java.util.function.Supplier;
/**
- * Monitors the network time. If looking up the network time fails for some reason, it tries a few
- * times with a short interval and then resets to checking on longer intervals.
+ * Refreshes network time periodically, when network connectivity becomes available and when the
+ * user enables automatic time detection.
*
- * <p>When available, the time is always suggested to the {@link
+ * <p>For periodic requests, this service attempts to leave an interval between successful requests.
+ * If a request fails, it retries a number of times with a "short" interval and then resets to the
+ * normal interval. The process then repeats.
+ *
+ * <p>When a valid network time is available, the time is always suggested to the {@link
* com.android.server.timedetector.TimeDetectorService} where it may be used to set the device
* system clock, depending on user settings and what other signals are available.
*/
@@ -72,25 +80,11 @@
private final Object mLock = new Object();
private final Context mContext;
- private final NtpTrustedTime mNtpTrustedTime;
- private final AlarmManager mAlarmManager;
- private final TimeDetectorInternal mTimeDetectorInternal;
private final ConnectivityManager mCM;
- private final PendingIntent mPendingPollIntent;
private final PowerManager.WakeLock mWakeLock;
-
- // Normal polling frequency
- private final int mNormalPollingIntervalMillis;
- // Try-again polling interval, in case the network request failed
- private final int mShortPollingIntervalMillis;
- // Number of times to try again
- private final int mTryAgainTimesMax;
-
- /**
- * A log that records the decisions to fetch a network time update.
- * This is logged in bug reports to assist with debugging issues with network time suggestions.
- */
- private final LocalLog mLocalLog = new LocalLog(30, false /* useLocalTimestamps */);
+ private final NtpTrustedTime mNtpTrustedTime;
+ private final Engine.RefreshCallbacks mRefreshCallbacks;
+ private final Engine mEngine;
// Blocking NTP lookup is done using this handler
private final Handler mHandler;
@@ -100,33 +94,43 @@
@Nullable
private Network mDefaultNetwork = null;
- // Keeps track of how many quick attempts were made to fetch NTP time.
- // During bootup, the network may not have been up yet, or it's taking time for the
- // connection to happen.
- // This field is only updated and accessed by the mHandler thread (except dump()).
- @GuardedBy("mLock")
- private int mTryAgainCounter;
-
public NetworkTimeUpdateService(@NonNull Context context) {
mContext = Objects.requireNonNull(context);
- mAlarmManager = mContext.getSystemService(AlarmManager.class);
- mTimeDetectorInternal = LocalServices.getService(TimeDetectorInternal.class);
mCM = mContext.getSystemService(ConnectivityManager.class);
mWakeLock = context.getSystemService(PowerManager.class).newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK, TAG);
mNtpTrustedTime = NtpTrustedTime.getInstance(context);
- mTryAgainTimesMax = mContext.getResources().getInteger(
+ Supplier<Long> elapsedRealtimeMillisSupplier = SystemClock::elapsedRealtime;
+ int tryAgainTimesMax = mContext.getResources().getInteger(
com.android.internal.R.integer.config_ntpRetry);
- mNormalPollingIntervalMillis = mContext.getResources().getInteger(
+ int normalPollingIntervalMillis = mContext.getResources().getInteger(
com.android.internal.R.integer.config_ntpPollingInterval);
- mShortPollingIntervalMillis = mContext.getResources().getInteger(
+ int shortPollingIntervalMillis = mContext.getResources().getInteger(
com.android.internal.R.integer.config_ntpPollingIntervalShorter);
+ mEngine = new EngineImpl(elapsedRealtimeMillisSupplier, normalPollingIntervalMillis,
+ shortPollingIntervalMillis, tryAgainTimesMax, mNtpTrustedTime);
+ AlarmManager alarmManager = mContext.getSystemService(AlarmManager.class);
+ TimeDetectorInternal timeDetectorInternal =
+ LocalServices.getService(TimeDetectorInternal.class);
// Broadcast alarms sent by system are immutable
Intent pollIntent = new Intent(ACTION_POLL, null);
- mPendingPollIntent = PendingIntent.getBroadcast(mContext, POLL_REQUEST,
+ PendingIntent pendingPollIntent = PendingIntent.getBroadcast(mContext, POLL_REQUEST,
pollIntent, PendingIntent.FLAG_IMMUTABLE);
+ mRefreshCallbacks = new Engine.RefreshCallbacks() {
+ @Override
+ public void scheduleNextRefresh(@ElapsedRealtimeLong long elapsedRealtimeMillis) {
+ alarmManager.cancel(pendingPollIntent);
+ alarmManager.set(
+ AlarmManager.ELAPSED_REALTIME, elapsedRealtimeMillis, pendingPollIntent);
+ }
+
+ @Override
+ public void submitSuggestion(NetworkTimeSuggestion suggestion) {
+ timeDetectorInternal.suggestNetworkTime(suggestion);
+ }
+ };
HandlerThread thread = new HandlerThread(TAG);
thread.start();
@@ -217,12 +221,7 @@
}
if (network == null) return false;
- boolean success = mNtpTrustedTime.forceRefresh(network);
- if (success) {
- makeNetworkTimeSuggestion(mNtpTrustedTime.getCachedTimeResult(),
- "Origin: NetworkTimeUpdateService: forceRefreshForTests");
- }
- return success;
+ return mEngine.forceRefreshForTests(network, mRefreshCallbacks);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -238,96 +237,12 @@
mWakeLock.acquire();
try {
- onPollNetworkTimeUnderWakeLock(network, reason);
+ mEngine.refreshIfRequiredAndReschedule(network, reason, mRefreshCallbacks);
} finally {
mWakeLock.release();
}
}
- private void onPollNetworkTimeUnderWakeLock(
- @NonNull Network network, @NonNull String reason) {
- long currentElapsedRealtimeMillis = SystemClock.elapsedRealtime();
-
- final int maxNetworkTimeAgeMillis = mNormalPollingIntervalMillis;
- // Force an NTP fix when outdated
- NtpTrustedTime.TimeResult cachedNtpResult = mNtpTrustedTime.getCachedTimeResult();
- if (cachedNtpResult == null
- || cachedNtpResult.getAgeMillis(currentElapsedRealtimeMillis)
- >= maxNetworkTimeAgeMillis) {
- if (DBG) Log.d(TAG, "Stale NTP fix; forcing refresh using network=" + network);
- boolean success = mNtpTrustedTime.forceRefresh(network);
- if (success) {
- synchronized (mLock) {
- mTryAgainCounter = 0;
- }
- } else {
- String logMsg = "forceRefresh() returned false:"
- + " cachedNtpResult=" + cachedNtpResult
- + ", currentElapsedRealtimeMillis=" + currentElapsedRealtimeMillis;
-
- if (DBG) {
- Log.d(TAG, logMsg);
- }
- mLocalLog.log(logMsg);
- }
-
- cachedNtpResult = mNtpTrustedTime.getCachedTimeResult();
- }
-
- if (cachedNtpResult != null
- && cachedNtpResult.getAgeMillis(currentElapsedRealtimeMillis)
- < maxNetworkTimeAgeMillis) {
- // Obtained fresh fix; schedule next normal update
- scheduleNextRefresh(mNormalPollingIntervalMillis
- - cachedNtpResult.getAgeMillis(currentElapsedRealtimeMillis));
-
- makeNetworkTimeSuggestion(cachedNtpResult, reason);
- } else {
- synchronized (mLock) {
- // No fresh fix; schedule retry
- mTryAgainCounter++;
- if (mTryAgainTimesMax < 0 || mTryAgainCounter <= mTryAgainTimesMax) {
- scheduleNextRefresh(mShortPollingIntervalMillis);
- } else {
- // Try much later
- String logMsg = "mTryAgainTimesMax exceeded,"
- + " cachedNtpResult=" + cachedNtpResult;
- if (DBG) {
- Log.d(TAG, logMsg);
- }
- mLocalLog.log(logMsg);
- mTryAgainCounter = 0;
-
- scheduleNextRefresh(mNormalPollingIntervalMillis);
- }
- }
- }
- }
-
- /** Suggests the time to the time detector. It may choose use it to set the system clock. */
- private void makeNetworkTimeSuggestion(
- @NonNull TimeResult ntpResult, @NonNull String debugInfo) {
- UnixEpochTime timeSignal = new UnixEpochTime(
- ntpResult.getElapsedRealtimeMillis(), ntpResult.getTimeMillis());
- NetworkTimeSuggestion timeSuggestion =
- new NetworkTimeSuggestion(timeSignal, ntpResult.getUncertaintyMillis());
- timeSuggestion.addDebugInfo(debugInfo);
- timeSuggestion.addDebugInfo(ntpResult.toString());
- mTimeDetectorInternal.suggestNetworkTime(timeSuggestion);
- }
-
- /**
- * Cancel old alarm and starts a new one for the specified interval.
- *
- * @param delayMillis when to trigger the alarm, starting from now.
- */
- private void scheduleNextRefresh(long delayMillis) {
- mAlarmManager.cancel(mPendingPollIntent);
- long now = SystemClock.elapsedRealtime();
- long next = now + delayMillis;
- mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, next, mPendingPollIntent);
- }
-
// All callbacks will be invoked using mHandler because of how the callback is registered.
private class NetworkTimeUpdateCallback extends NetworkCallback {
@Override
@@ -385,21 +300,10 @@
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
- pw.println("mNormalPollingIntervalMillis="
- + Duration.ofMillis(mNormalPollingIntervalMillis));
- pw.println("mShortPollingIntervalMillis="
- + Duration.ofMillis(mShortPollingIntervalMillis));
- pw.println("mTryAgainTimesMax=" + mTryAgainTimesMax);
synchronized (mLock) {
pw.println("mDefaultNetwork=" + mDefaultNetwork);
- pw.println("mTryAgainCounter=" + mTryAgainCounter);
}
- pw.println();
- pw.println("NtpTrustedTime:");
- mNtpTrustedTime.dump(pw);
- pw.println();
- pw.println("Local logs:");
- mLocalLog.dump(fd, pw, args);
+ mEngine.dump(pw);
pw.println();
}
@@ -409,4 +313,331 @@
new NetworkTimeUpdateServiceShellCommand(this).exec(
this, in, out, err, args, callback, resultReceiver);
}
+
+ /**
+ * The interface the service uses to interact with the time refresh logic.
+ * Extracted for testing.
+ */
+ @VisibleForTesting
+ interface Engine {
+ interface RefreshCallbacks {
+ void scheduleNextRefresh(@ElapsedRealtimeLong long elapsedRealtimeMillis);
+
+ void submitSuggestion(@NonNull NetworkTimeSuggestion suggestion);
+ }
+
+ /**
+ * Forces the engine to refresh the network time (for tests). See {@link
+ * NetworkTimeUpdateService#forceRefreshForTests()}. This is a blocking call. This method
+ * must not schedule any calls.
+ */
+ boolean forceRefreshForTests(
+ @NonNull Network network, @NonNull RefreshCallbacks refreshCallbacks);
+
+ /**
+ * Attempts to refresh the network time if required, i.e. if there isn't a recent-enough
+ * network time available. It must also schedule the next call. This is a blocking call.
+ *
+ * @param network the network to use
+ * @param reason the reason for the refresh (for logging)
+ */
+ void refreshIfRequiredAndReschedule(@NonNull Network network, @NonNull String reason,
+ @NonNull RefreshCallbacks refreshCallbacks);
+
+ void dump(@NonNull PrintWriter pw);
+ }
+
+ @VisibleForTesting
+ static class EngineImpl implements Engine {
+
+ /**
+ * A log that records the decisions to fetch a network time update.
+ * This is logged in bug reports to assist with debugging issues with network time
+ * suggestions.
+ */
+ @NonNull
+ private final LocalLog mLocalDebugLog = new LocalLog(30, false /* useLocalTimestamps */);
+
+ /**
+ * The usual interval between refresh attempts. Always used after a successful request.
+ *
+ * <p>The value also determines whether a network time result is considered fresh.
+ * Refreshes only take place from this class when the latest time result is considered too
+ * old.
+ */
+ private final int mNormalPollingIntervalMillis;
+
+ /**
+ * A shortened interval between refresh attempts used after a failure to refresh.
+ * Always shorter than {@link #mNormalPollingIntervalMillis} and only used when {@link
+ * #mTryAgainTimesMax} != 0.
+ *
+ * <p>This value is also the lower bound for the interval allowed between successive
+ * refreshes when the latest time result is missing or too old, e.g. a refresh may not be
+ * triggered when network connectivity is restored if the last attempt was too recent.
+ */
+ private final int mShortPollingIntervalMillis;
+
+ /**
+ * The number of times {@link #mShortPollingIntervalMillis} can be used after successive
+ * failures before switching back to using {@link #mNormalPollingIntervalMillis} once before
+ * repeating. When this value is negative, the refresh algorithm will continue to use {@link
+ * #mShortPollingIntervalMillis} until a successful refresh.
+ */
+ private final int mTryAgainTimesMax;
+
+ private final NtpTrustedTime mNtpTrustedTime;
+
+ /**
+ * Records the time of the last refresh attempt (successful or otherwise) by this service.
+ * This is used when scheduling the next refresh attempt. In cases where {@link
+ * #refreshIfRequiredAndReschedule} is called too frequently, this will prevent each call
+ * resulting in a network request. See also {@link #mShortPollingIntervalMillis}.
+ *
+ * <p>Time servers are a shared resource and so Android should avoid loading them.
+ * Generally, a refresh attempt will succeed and the service won't need to make further
+ * requests and this field will not limit requests.
+ */
+ // This field is only updated and accessed by the mHandler thread (except dump()).
+ @GuardedBy("this")
+ @ElapsedRealtimeLong
+ private Long mLastRefreshAttemptElapsedRealtimeMillis;
+
+ /**
+ * Keeps track of successive time refresh failures have occurred. This is reset to zero when
+ * time refresh is successful or if the number exceeds (a non-negative) {@link
+ * #mTryAgainTimesMax}.
+ */
+ @GuardedBy("this")
+ private int mTryAgainCounter;
+
+ private final Supplier<Long> mElapsedRealtimeMillisSupplier;
+
+ @VisibleForTesting
+ EngineImpl(@NonNull Supplier<Long> elapsedRealtimeMillisSupplier,
+ int normalPollingIntervalMillis, int shortPollingIntervalMillis,
+ int tryAgainTimesMax, @NonNull NtpTrustedTime ntpTrustedTime) {
+ mElapsedRealtimeMillisSupplier = Objects.requireNonNull(elapsedRealtimeMillisSupplier);
+ if (shortPollingIntervalMillis > normalPollingIntervalMillis) {
+ throw new IllegalArgumentException(String.format(
+ "shortPollingIntervalMillis (%s) > normalPollingIntervalMillis (%s)",
+ shortPollingIntervalMillis, normalPollingIntervalMillis));
+ }
+ mNormalPollingIntervalMillis = normalPollingIntervalMillis;
+ mShortPollingIntervalMillis = shortPollingIntervalMillis;
+ mTryAgainTimesMax = tryAgainTimesMax;
+ mNtpTrustedTime = Objects.requireNonNull(ntpTrustedTime);
+ }
+
+ @Override
+ public boolean forceRefreshForTests(
+ @NonNull Network network, @NonNull RefreshCallbacks refreshCallbacks) {
+ boolean refreshSuccessful = tryRefresh(network);
+ logToDebugAndDumpsys("forceRefreshForTests: refreshSuccessful=" + refreshSuccessful);
+
+ if (refreshSuccessful) {
+ makeNetworkTimeSuggestion(mNtpTrustedTime.getCachedTimeResult(),
+ "EngineImpl.forceRefreshForTests()", refreshCallbacks);
+ }
+ return refreshSuccessful;
+ }
+
+ @Override
+ public void refreshIfRequiredAndReschedule(
+ @NonNull Network network, @NonNull String reason,
+ @NonNull RefreshCallbacks refreshCallbacks) {
+ // Attempt to refresh the network time if there is no latest time result, or if the
+ // latest time result is considered too old.
+ NtpTrustedTime.TimeResult initialTimeResult = mNtpTrustedTime.getCachedTimeResult();
+ boolean shouldAttemptRefresh;
+ synchronized (this) {
+ long currentElapsedRealtimeMillis = mElapsedRealtimeMillisSupplier.get();
+
+ // calculateTimeResultAgeMillis() safely handles a null initialTimeResult.
+ long timeResultAgeMillis = calculateTimeResultAgeMillis(
+ initialTimeResult, currentElapsedRealtimeMillis);
+ shouldAttemptRefresh =
+ timeResultAgeMillis >= mNormalPollingIntervalMillis
+ && isRefreshAllowed(currentElapsedRealtimeMillis);
+ }
+
+ boolean refreshSuccessful = false;
+ if (shouldAttemptRefresh) {
+ // This is a blocking call. Deliberately invoked without holding the "this" monitor
+ // to avoid blocking logic that wants to use the "this" monitor.
+ refreshSuccessful = tryRefresh(network);
+ }
+
+ synchronized (this) {
+ // Manage mTryAgainCounter.
+ if (shouldAttemptRefresh) {
+ if (refreshSuccessful) {
+ // Reset failure tracking.
+ mTryAgainCounter = 0;
+ } else {
+ if (mTryAgainTimesMax < 0) {
+ // When mTryAgainTimesMax is negative there's no enforced maximum and
+ // short intervals should be used until a successful refresh. Setting
+ // mTryAgainCounter to 1 is sufficient for the interval calculations
+ // below. There's no need to increment.
+ mTryAgainCounter = 1;
+ } else {
+ mTryAgainCounter++;
+ if (mTryAgainCounter > mTryAgainTimesMax) {
+ mTryAgainCounter = 0;
+ }
+ }
+ }
+ }
+
+ // currentElapsedRealtimeMillis is used to evaluate ages and refresh scheduling
+ // below. Capturing this after a possible successful refresh ensures that latest
+ // time result ages will be >= 0.
+ long currentElapsedRealtimeMillis = mElapsedRealtimeMillisSupplier.get();
+
+ // This section of code deliberately doesn't assume it is the only component using
+ // mNtpTrustedTime to obtain NTP times: another component in the same process could
+ // be gathering NTP signals (which then won't have been suggested to the time
+ // detector).
+ // TODO(b/222295093): Make this class the sole owner of mNtpTrustedTime and
+ // simplify / reduce duplicate suggestions.
+ NtpTrustedTime.TimeResult latestTimeResult = mNtpTrustedTime.getCachedTimeResult();
+ long latestTimeResultAgeMillis = calculateTimeResultAgeMillis(
+ latestTimeResult, currentElapsedRealtimeMillis);
+
+ // Suggest the latest time result to the time detector if it is fresh regardless of
+ // whether refresh happened above.
+ if (latestTimeResultAgeMillis < mNormalPollingIntervalMillis) {
+ // We assume the time detector service will detect duplicate suggestions and not
+ // do more work than it has to, so no need to avoid making duplicate
+ // suggestions.
+ makeNetworkTimeSuggestion(latestTimeResult, reason, refreshCallbacks);
+ }
+
+ // (Re)schedule the next refresh based on the latest state.
+ // Determine which refresh delay to use by using the current value of
+ // mTryAgainCounter. The refresh delay is applied to a different point in time
+ // depending on whether the latest available time result (if any) is still
+ // considered fresh to ensure the delay acts correctly.
+ long refreshDelayMillis = mTryAgainCounter > 0
+ ? mShortPollingIntervalMillis : mNormalPollingIntervalMillis;
+ long nextRefreshElapsedRealtimeMillis;
+ if (latestTimeResultAgeMillis < mNormalPollingIntervalMillis) {
+ // The latest time result is fresh, use it to determine when next to refresh.
+ nextRefreshElapsedRealtimeMillis =
+ latestTimeResult.getElapsedRealtimeMillis() + refreshDelayMillis;
+ } else if (mLastRefreshAttemptElapsedRealtimeMillis != null) {
+ // The latest time result is missing or old and still needs to be refreshed.
+ // mLastRefreshAttemptElapsedRealtimeMillis, which should always be set by this
+ // point because there's no fresh time result, should be very close to
+ // currentElapsedRealtimeMillis unless the refresh was not allowed.
+ nextRefreshElapsedRealtimeMillis =
+ mLastRefreshAttemptElapsedRealtimeMillis + refreshDelayMillis;
+ } else {
+ // This should not happen: mLastRefreshAttemptElapsedRealtimeMillis should
+ // always be non-null by this point.
+ logToDebugAndDumpsys(
+ "mLastRefreshAttemptElapsedRealtimeMillis unexpectedly missing."
+ + " Scheduling using currentElapsedRealtimeMillis");
+ nextRefreshElapsedRealtimeMillis =
+ currentElapsedRealtimeMillis + refreshDelayMillis;
+ }
+ refreshCallbacks.scheduleNextRefresh(nextRefreshElapsedRealtimeMillis);
+
+ logToDebugAndDumpsys("refreshIfRequiredAndReschedule:"
+ + " network=" + network
+ + ", reason=" + reason
+ + ", initialTimeResult=" + initialTimeResult
+ + ", shouldAttemptRefresh=" + shouldAttemptRefresh
+ + ", refreshSuccessful=" + refreshSuccessful
+ + ", currentElapsedRealtimeMillis="
+ + formatElapsedRealtimeMillis(currentElapsedRealtimeMillis)
+ + ", latestTimeResult=" + latestTimeResult
+ + ", mTryAgainCounter=" + mTryAgainCounter
+ + ", refreshDelayMillis=" + refreshDelayMillis
+ + ", nextRefreshElapsedRealtimeMillis="
+ + formatElapsedRealtimeMillis(nextRefreshElapsedRealtimeMillis));
+ }
+ }
+
+ private static String formatElapsedRealtimeMillis(
+ @ElapsedRealtimeLong long elapsedRealtimeMillis) {
+ return Duration.ofMillis(elapsedRealtimeMillis) + " (" + elapsedRealtimeMillis + ")";
+ }
+
+ private static long calculateTimeResultAgeMillis(
+ @Nullable TimeResult timeResult,
+ @ElapsedRealtimeLong long currentElapsedRealtimeMillis) {
+ return timeResult == null ? Long.MAX_VALUE
+ : timeResult.getAgeMillis(currentElapsedRealtimeMillis);
+ }
+
+ @GuardedBy("this")
+ private boolean isRefreshAllowed(@ElapsedRealtimeLong long currentElapsedRealtimeMillis) {
+ if (mLastRefreshAttemptElapsedRealtimeMillis == null) {
+ return true;
+ }
+ // Use the second meaning of mShortPollingIntervalMillis: to determine the minimum time
+ // allowed after an unsuccessful refresh before another can be attempted.
+ long nextRefreshAllowedElapsedRealtimeMillis =
+ mLastRefreshAttemptElapsedRealtimeMillis + mShortPollingIntervalMillis;
+ return currentElapsedRealtimeMillis >= nextRefreshAllowedElapsedRealtimeMillis;
+ }
+
+ private boolean tryRefresh(@NonNull Network network) {
+ long currentElapsedRealtimeMillis = mElapsedRealtimeMillisSupplier.get();
+ synchronized (this) {
+ mLastRefreshAttemptElapsedRealtimeMillis = currentElapsedRealtimeMillis;
+ }
+ return mNtpTrustedTime.forceRefresh(network);
+ }
+
+ /** Suggests the time to the time detector. It may choose use it to set the system clock. */
+ private void makeNetworkTimeSuggestion(@NonNull TimeResult ntpResult,
+ @NonNull String debugInfo, @NonNull RefreshCallbacks refreshCallbacks) {
+ UnixEpochTime timeSignal = new UnixEpochTime(
+ ntpResult.getElapsedRealtimeMillis(), ntpResult.getTimeMillis());
+ NetworkTimeSuggestion timeSuggestion =
+ new NetworkTimeSuggestion(timeSignal, ntpResult.getUncertaintyMillis());
+ timeSuggestion.addDebugInfo(debugInfo);
+ timeSuggestion.addDebugInfo(ntpResult.toString());
+ refreshCallbacks.submitSuggestion(timeSuggestion);
+ }
+
+ @Override
+ public void dump(PrintWriter pw) {
+ IndentingPrintWriter ipw = new IndentingPrintWriter(pw);
+ ipw.println("mNormalPollingIntervalMillis=" + mNormalPollingIntervalMillis);
+ ipw.println("mShortPollingIntervalMillis=" + mShortPollingIntervalMillis);
+ ipw.println("mTryAgainTimesMax=" + mTryAgainTimesMax);
+
+ synchronized (this) {
+ String lastRefreshAttemptValue = mLastRefreshAttemptElapsedRealtimeMillis == null
+ ? "null"
+ : formatElapsedRealtimeMillis(mLastRefreshAttemptElapsedRealtimeMillis);
+ ipw.println("mLastRefreshAttemptElapsedRealtimeMillis=" + lastRefreshAttemptValue);
+ ipw.println("mTryAgainCounter=" + mTryAgainCounter);
+ }
+ ipw.println();
+
+ ipw.println("NtpTrustedTime:");
+ ipw.increaseIndent();
+ mNtpTrustedTime.dump(ipw);
+ ipw.decreaseIndent();
+ ipw.println();
+
+ ipw.println("Debug log:");
+ ipw.increaseIndent();
+ mLocalDebugLog.dump(ipw);
+ ipw.decreaseIndent();
+ ipw.println();
+ }
+
+ private void logToDebugAndDumpsys(String logMsg) {
+ if (DBG) {
+ Log.d(TAG, logMsg);
+ }
+ mLocalDebugLog.log(logMsg);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorService.java b/services/core/java/com/android/server/timedetector/TimeDetectorService.java
index 1be9074..3e23953 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorService.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorService.java
@@ -143,7 +143,7 @@
return getTimeCapabilitiesAndConfig(userId);
}
- TimeCapabilitiesAndConfig getTimeCapabilitiesAndConfig(@UserIdInt int userId) {
+ private TimeCapabilitiesAndConfig getTimeCapabilitiesAndConfig(@UserIdInt int userId) {
enforceManageTimeDetectorPermission();
final long token = mCallerIdentityInjector.clearCallingIdentity();
@@ -163,6 +163,9 @@
return updateConfiguration(callingUserId, configuration);
}
+ /**
+ * Updates the user's configuration. Exposed for use by {@link TimeDetectorShellCommand}.
+ */
boolean updateConfiguration(@UserIdInt int userId, @NonNull TimeConfiguration configuration) {
// Resolve constants like USER_CURRENT to the true user ID as needed.
int resolvedUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
@@ -256,7 +259,7 @@
}
}
- void handleConfigurationInternalChangedOnHandlerThread() {
+ private void handleConfigurationInternalChangedOnHandlerThread() {
// Configuration has changed, but each user may have a different view of the configuration.
// It's possible that this will cause unnecessary notifications but that shouldn't be a
// problem.
@@ -287,6 +290,10 @@
}
}
+ /**
+ * Sets the system time state. See {@link TimeState} for details. For use by {@link
+ * TimeDetectorShellCommand}.
+ */
void setTimeState(@NonNull TimeState timeState) {
enforceManageTimeDetectorPermission();
@@ -353,6 +360,9 @@
}
}
+ /**
+ * Suggests network time with permission checks. For use by {@link TimeDetectorShellCommand}.
+ */
void suggestNetworkTime(@NonNull NetworkTimeSuggestion timeSignal) {
enforceSuggestNetworkTimePermission();
Objects.requireNonNull(timeSignal);
@@ -360,6 +370,23 @@
mHandler.post(() -> mTimeDetectorStrategy.suggestNetworkTime(timeSignal));
}
+ /**
+ * Clears the cached network time information. For use during tests to simulate when no network
+ * time has been made available. For use by {@link TimeDetectorShellCommand}.
+ *
+ * <p>This operation takes place in the calling thread.
+ */
+ void clearNetworkTime() {
+ enforceSuggestNetworkTimePermission();
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mTimeDetectorStrategy.clearLatestNetworkSuggestion();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
@Override
public UnixEpochTime latestNetworkTime() {
NetworkTimeSuggestion suggestion = getLatestNetworkSuggestion();
@@ -388,6 +415,9 @@
}
}
+ /**
+ * Suggests GNSS time with permission checks. For use by {@link TimeDetectorShellCommand}.
+ */
void suggestGnssTime(@NonNull GnssTimeSuggestion timeSignal) {
enforceSuggestGnssTimePermission();
Objects.requireNonNull(timeSignal);
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorShellCommand.java b/services/core/java/com/android/server/timedetector/TimeDetectorShellCommand.java
index 990c00f..cce5709 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorShellCommand.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorShellCommand.java
@@ -15,7 +15,9 @@
*/
package com.android.server.timedetector;
+import static android.app.timedetector.TimeDetector.SHELL_COMMAND_CLEAR_NETWORK_TIME;
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_CONFIRM_TIME;
+import static android.app.timedetector.TimeDetector.SHELL_COMMAND_GET_NETWORK_TIME;
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_GET_TIME_STATE;
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_IS_AUTO_DETECTION_ENABLED;
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SERVICE_NAME;
@@ -70,6 +72,10 @@
return runSuggestTelephonyTime();
case SHELL_COMMAND_SUGGEST_NETWORK_TIME:
return runSuggestNetworkTime();
+ case SHELL_COMMAND_GET_NETWORK_TIME:
+ return runGetNetworkTime();
+ case SHELL_COMMAND_CLEAR_NETWORK_TIME:
+ return runClearNetworkTime();
case SHELL_COMMAND_SUGGEST_GNSS_TIME:
return runSuggestGnssTime();
case SHELL_COMMAND_SUGGEST_EXTERNAL_TIME:
@@ -122,6 +128,18 @@
mInterface::suggestNetworkTime);
}
+ private int runGetNetworkTime() {
+ NetworkTimeSuggestion networkTimeSuggestion = mInterface.getLatestNetworkSuggestion();
+ final PrintWriter pw = getOutPrintWriter();
+ pw.println(networkTimeSuggestion);
+ return 0;
+ }
+
+ private int runClearNetworkTime() {
+ mInterface.clearNetworkTime();
+ return 0;
+ }
+
private int runSuggestGnssTime() {
return runSuggestTime(
() -> GnssTimeSuggestion.parseCommandLineArg(this),
@@ -196,6 +214,10 @@
pw.printf(" Sets the current time state for tests.\n");
pw.printf(" %s <unix epoch time options>\n", SHELL_COMMAND_CONFIRM_TIME);
pw.printf(" Tries to confirms the time, raising the confidence.\n");
+ pw.printf(" %s\n", SHELL_COMMAND_GET_NETWORK_TIME);
+ pw.printf(" Prints the network time information held by the detector.\n");
+ pw.printf(" %s\n", SHELL_COMMAND_CLEAR_NETWORK_TIME);
+ pw.printf(" Clears the network time information held by the detector.\n");
pw.println();
ManualTimeSuggestion.printCommandLineOpts(pw);
pw.println();
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
index 03f236d..9dca6ec 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
@@ -18,6 +18,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.time.ExternalTimeSuggestion;
import android.app.time.TimeState;
@@ -103,6 +104,20 @@
/** Processes the suggested time from network sources. */
void suggestNetworkTime(@NonNull NetworkTimeSuggestion timeSuggestion);
+ /**
+ * Returns the latest (accepted) network time suggestion. Returns {@code null} if there isn't
+ * one.
+ */
+ @Nullable
+ NetworkTimeSuggestion getLatestNetworkSuggestion();
+
+ /**
+ * Clears the latest network time suggestion, leaving none. The remaining time signals from
+ * other sources will be reassessed causing the device's time to be updated if config and
+ * settings allow.
+ */
+ void clearLatestNetworkSuggestion();
+
/** Processes the suggested time from gnss sources. */
void suggestGnssTime(@NonNull GnssTimeSuggestion timeSuggestion);
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
index 13ec753..09bb803 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
@@ -316,6 +316,21 @@
}
@Override
+ @Nullable
+ public synchronized NetworkTimeSuggestion getLatestNetworkSuggestion() {
+ return mLastNetworkSuggestion.get();
+ }
+
+ @Override
+ public synchronized void clearLatestNetworkSuggestion() {
+ mLastNetworkSuggestion.set(null);
+
+ // The loss of network time may change the time signal to use to set the system clock.
+ String reason = "Network time cleared";
+ doAutoTimeDetection(reason);
+ }
+
+ @Override
@NonNull
public synchronized TimeState getTimeState() {
boolean userShouldConfirmTime = mEnvironment.systemClockConfidence() < TIME_CONFIDENCE_HIGH;
@@ -1068,15 +1083,6 @@
*/
@VisibleForTesting
@Nullable
- public synchronized NetworkTimeSuggestion getLatestNetworkSuggestion() {
- return mLastNetworkSuggestion.get();
- }
-
- /**
- * A method used to inspect state during tests. Not intended for general use.
- */
- @VisibleForTesting
- @Nullable
public synchronized GnssTimeSuggestion getLatestGnssSuggestion() {
return mLastGnssSuggestion.get();
}
diff --git a/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java b/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java
index ebee995..d4f2f2d 100644
--- a/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java
+++ b/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java
@@ -24,11 +24,13 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
import android.graphics.Rect;
+import android.media.PlaybackParams;
import android.media.tv.AdBuffer;
import android.media.tv.AdRequest;
import android.media.tv.AdResponse;
@@ -85,6 +87,11 @@
public class TvInteractiveAppManagerService extends SystemService {
private static final boolean DEBUG = false;
private static final String TAG = "TvInteractiveAppManagerService";
+
+ private static final String METADATA_CLASS_NAME =
+ "android.media.tv.interactive.AppLinkInfo.ClassName";
+ private static final String METADATA_URI =
+ "android.media.tv.interactive.AppLinkInfo.Uri";
// A global lock.
private final Object mLock = new Object();
private final Context mContext;
@@ -101,6 +108,8 @@
// TODO: remove mGetServiceListCalled if onBootPhrase work correctly
@GuardedBy("mLock")
private boolean mGetServiceListCalled = false;
+ @GuardedBy("mLock")
+ private boolean mGetAppLinkInfoListCalled = false;
private final UserManager mUserManager;
@@ -120,6 +129,41 @@
}
@GuardedBy("mLock")
+ private void buildAppLinkInfoLocked(int userId) {
+ UserState userState = getOrCreateUserStateLocked(userId);
+ if (DEBUG) {
+ Slogf.d(TAG, "buildAppLinkInfoLocked");
+ }
+ PackageManager pm = mContext.getPackageManager();
+ List<ApplicationInfo> appInfos = pm.getInstalledApplicationsAsUser(
+ PackageManager.ApplicationInfoFlags.of(PackageManager.GET_META_DATA), userId);
+ List<AppLinkInfo> appLinkInfos = new ArrayList<>();
+ for (ApplicationInfo appInfo : appInfos) {
+ AppLinkInfo info = buildAppLinkInfoLocked(appInfo);
+ if (info != null) {
+ appLinkInfos.add(info);
+ }
+ }
+ // sort the list by package name
+ Collections.sort(appLinkInfos, Comparator.comparing(AppLinkInfo::getComponentName));
+ userState.mAppLinkInfoList.clear();
+ userState.mAppLinkInfoList.addAll(appLinkInfos);
+ }
+
+ @GuardedBy("mLock")
+ private AppLinkInfo buildAppLinkInfoLocked(ApplicationInfo appInfo) {
+ if (appInfo.metaData == null || appInfo.packageName == null) {
+ return null;
+ }
+ String className = appInfo.metaData.getString(METADATA_CLASS_NAME, null);
+ String uri = appInfo.metaData.getString(METADATA_URI, null);
+ if (className == null || uri == null) {
+ return null;
+ }
+ return new AppLinkInfo(appInfo.packageName, className, uri);
+ }
+
+ @GuardedBy("mLock")
private void buildTvInteractiveAppServiceListLocked(int userId, String[] updatedPackages) {
UserState userState = getOrCreateUserStateLocked(userId);
userState.mPackageSet.clear();
@@ -310,6 +354,7 @@
} else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
synchronized (mLock) {
buildTvInteractiveAppServiceListLocked(mCurrentUserId, null);
+ buildAppLinkInfoLocked(mCurrentUserId);
}
}
}
@@ -321,6 +366,7 @@
synchronized (mLock) {
if (mCurrentUserId == userId || mRunningProfiles.contains(userId)) {
buildTvInteractiveAppServiceListLocked(userId, packages);
+ buildAppLinkInfoLocked(userId);
}
}
}
@@ -427,6 +473,7 @@
mCurrentUserId = userId;
buildTvInteractiveAppServiceListLocked(userId, null);
+ buildAppLinkInfoLocked(userId);
}
}
@@ -512,6 +559,7 @@
private void startProfileLocked(int userId) {
mRunningProfiles.add(userId);
buildTvInteractiveAppServiceListLocked(userId, null);
+ buildAppLinkInfoLocked(userId);
}
@GuardedBy("mLock")
@@ -667,6 +715,26 @@
}
@Override
+ public List<AppLinkInfo> getAppLinkInfoList(int userId) {
+ final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(),
+ Binder.getCallingUid(), userId, "getAppLinkInfoList");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ if (!mGetAppLinkInfoListCalled) {
+ buildAppLinkInfoLocked(userId);
+ mGetAppLinkInfoListCalled = true;
+ }
+ UserState userState = getOrCreateUserStateLocked(resolvedUserId);
+ List<AppLinkInfo> appLinkInfos = new ArrayList<>(userState.mAppLinkInfoList);
+ return appLinkInfos;
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
public void registerAppLinkInfo(String tiasId, AppLinkInfo appLinkInfo, int userId) {
final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(),
Binder.getCallingUid(), userId, "registerAppLinkInfo: " + appLinkInfo);
@@ -1268,6 +1336,31 @@
}
@Override
+ public void sendCurrentVideoBounds(IBinder sessionToken, Rect bounds, int userId) {
+ if (DEBUG) {
+ Slogf.d(TAG, "sendCurrentVideoBounds(bounds=%s)", bounds.toString());
+ }
+ final int callingUid = Binder.getCallingUid();
+ final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
+ userId, "sendCurrentVideoBounds");
+ SessionState sessionState = null;
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ try {
+ sessionState = getSessionStateLocked(sessionToken, callingUid,
+ resolvedUserId);
+ getSessionLocked(sessionState).sendCurrentVideoBounds(bounds);
+ } catch (RemoteException | SessionNotFoundException e) {
+ Slogf.e(TAG, "error in sendCurrentVideoBounds", e);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
public void sendCurrentChannelUri(IBinder sessionToken, Uri channelUri, int userId) {
if (DEBUG) {
Slogf.d(TAG, "sendCurrentChannelUri(channelUri=%s)", channelUri.toString());
@@ -1496,6 +1589,118 @@
}
@Override
+ public void notifyTimeShiftPlaybackParams(
+ IBinder sessionToken, PlaybackParams params, int userId) {
+ if (DEBUG) {
+ Slogf.d(TAG, "notifyTimeShiftPlaybackParams(params=%s)", params);
+ }
+ final int callingUid = Binder.getCallingUid();
+ final int resolvedUserId = resolveCallingUserId(
+ Binder.getCallingPid(), callingUid, userId, "notifyTimeShiftPlaybackParams");
+ SessionState sessionState = null;
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ try {
+ sessionState =
+ getSessionStateLocked(sessionToken, callingUid, resolvedUserId);
+ getSessionLocked(sessionState).notifyTimeShiftPlaybackParams(params);
+ } catch (RemoteException | SessionNotFoundException e) {
+ Slogf.e(TAG, "error in notifyTimeShiftPlaybackParams", e);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void notifyTimeShiftStatusChanged(
+ IBinder sessionToken, String inputId, int status, int userId) {
+ if (DEBUG) {
+ Slogf.d(TAG, "notifyTimeShiftStatusChanged(inputId=%s, status=%d)",
+ inputId, status);
+ }
+ final int callingUid = Binder.getCallingUid();
+ final int resolvedUserId = resolveCallingUserId(
+ Binder.getCallingPid(), callingUid, userId, "notifyTimeShiftStatusChanged");
+ SessionState sessionState = null;
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ try {
+ sessionState =
+ getSessionStateLocked(sessionToken, callingUid, resolvedUserId);
+ getSessionLocked(sessionState).notifyTimeShiftStatusChanged(
+ inputId, status);
+ } catch (RemoteException | SessionNotFoundException e) {
+ Slogf.e(TAG, "error in notifyTimeShiftStatusChanged", e);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void notifyTimeShiftStartPositionChanged(
+ IBinder sessionToken, String inputId, long timeMs, int userId) {
+ if (DEBUG) {
+ Slogf.d(TAG, "notifyTimeShiftStartPositionChanged(inputId=%s, timeMs=%d)",
+ inputId, timeMs);
+ }
+ final int callingUid = Binder.getCallingUid();
+ final int resolvedUserId = resolveCallingUserId(
+ Binder.getCallingPid(), callingUid, userId,
+ "notifyTimeShiftStartPositionChanged");
+ SessionState sessionState = null;
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ try {
+ sessionState =
+ getSessionStateLocked(sessionToken, callingUid, resolvedUserId);
+ getSessionLocked(sessionState).notifyTimeShiftStartPositionChanged(
+ inputId, timeMs);
+ } catch (RemoteException | SessionNotFoundException e) {
+ Slogf.e(TAG, "error in notifyTimeShiftStartPositionChanged", e);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void notifyTimeShiftCurrentPositionChanged(
+ IBinder sessionToken, String inputId, long timeMs, int userId) {
+ if (DEBUG) {
+ Slogf.d(TAG, "notifyTimeShiftCurrentPositionChanged(inputId=%s, timeMs=%d)",
+ inputId, timeMs);
+ }
+ final int callingUid = Binder.getCallingUid();
+ final int resolvedUserId = resolveCallingUserId(
+ Binder.getCallingPid(), callingUid, userId,
+ "notifyTimeShiftCurrentPositionChanged");
+ SessionState sessionState = null;
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ try {
+ sessionState =
+ getSessionStateLocked(sessionToken, callingUid, resolvedUserId);
+ getSessionLocked(sessionState).notifyTimeShiftCurrentPositionChanged(
+ inputId, timeMs);
+ } catch (RemoteException | SessionNotFoundException e) {
+ Slogf.e(TAG, "error in notifyTimeShiftCurrentPositionChanged", e);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
public void setSurface(IBinder sessionToken, Surface surface, int userId) {
final int callingUid = Binder.getCallingUid();
final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
@@ -1883,6 +2088,8 @@
// A set of all TV Interactive App service packages.
private final Set<String> mPackageSet = new HashSet<>();
+ // A list of all app link infos.
+ private final List<AppLinkInfo> mAppLinkInfoList = new ArrayList<>();
// A list of callbacks.
private final RemoteCallbackList<ITvInteractiveAppManagerCallback> mCallbacks =
@@ -2255,6 +2462,27 @@
}
@Override
+ public void onTimeShiftCommandRequest(
+ @TvInteractiveAppService.TimeShiftCommandType String cmdType,
+ Bundle parameters) {
+ synchronized (mLock) {
+ if (DEBUG) {
+ Slogf.d(TAG, "onTimeShiftCommandRequest (cmdType=" + cmdType
+ + ", parameters=" + parameters.toString() + ")");
+ }
+ if (mSessionState.mSession == null || mSessionState.mClient == null) {
+ return;
+ }
+ try {
+ mSessionState.mClient.onTimeShiftCommandRequest(
+ cmdType, parameters, mSessionState.mSeq);
+ } catch (RemoteException e) {
+ Slogf.e(TAG, "error in onTimeShiftCommandRequest", e);
+ }
+ }
+ }
+
+ @Override
public void onSetVideoBounds(Rect rect) {
synchronized (mLock) {
if (DEBUG) {
@@ -2272,6 +2500,23 @@
}
@Override
+ public void onRequestCurrentVideoBounds() {
+ synchronized (mLock) {
+ if (DEBUG) {
+ Slogf.d(TAG, "onRequestCurrentVideoBounds");
+ }
+ if (mSessionState.mSession == null || mSessionState.mClient == null) {
+ return;
+ }
+ try {
+ mSessionState.mClient.onRequestCurrentVideoBounds(mSessionState.mSeq);
+ } catch (RemoteException e) {
+ Slogf.e(TAG, "error in onRequestCurrentVideoBounds", e);
+ }
+ }
+ }
+
+ @Override
public void onRequestCurrentChannelUri() {
synchronized (mLock) {
if (DEBUG) {
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperData.java b/services/core/java/com/android/server/wallpaper/WallpaperData.java
index 79de282..25ce280 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperData.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperData.java
@@ -18,10 +18,10 @@
import static android.app.WallpaperManager.FLAG_LOCK;
-import static com.android.server.wallpaper.WallpaperManagerService.WALLPAPER;
-import static com.android.server.wallpaper.WallpaperManagerService.WALLPAPER_CROP;
-import static com.android.server.wallpaper.WallpaperManagerService.WALLPAPER_LOCK_CROP;
-import static com.android.server.wallpaper.WallpaperManagerService.WALLPAPER_LOCK_ORIG;
+import static com.android.server.wallpaper.WallpaperUtils.WALLPAPER;
+import static com.android.server.wallpaper.WallpaperUtils.WALLPAPER_CROP;
+import static com.android.server.wallpaper.WallpaperUtils.WALLPAPER_LOCK_CROP;
+import static com.android.server.wallpaper.WallpaperUtils.WALLPAPER_LOCK_ORIG;
import static com.android.server.wallpaper.WallpaperUtils.getWallpaperDir;
import android.app.IWallpaperManagerCallback;
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 3d59b7b..6edfebf 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -32,7 +32,14 @@
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
+import static com.android.server.wallpaper.WallpaperUtils.RECORD_FILE;
+import static com.android.server.wallpaper.WallpaperUtils.RECORD_LOCK_FILE;
+import static com.android.server.wallpaper.WallpaperUtils.WALLPAPER;
+import static com.android.server.wallpaper.WallpaperUtils.WALLPAPER_CROP;
+import static com.android.server.wallpaper.WallpaperUtils.WALLPAPER_INFO;
+import static com.android.server.wallpaper.WallpaperUtils.WALLPAPER_LOCK_ORIG;
import static com.android.server.wallpaper.WallpaperUtils.getWallpaperDir;
+import static com.android.server.wallpaper.WallpaperUtils.makeWallpaperIdLocked;
import android.annotation.NonNull;
import android.app.ActivityManager;
@@ -199,20 +206,6 @@
*/
private static final long MIN_WALLPAPER_CRASH_TIME = 10000;
private static final int MAX_WALLPAPER_COMPONENT_LOG_LENGTH = 128;
- static final String WALLPAPER = "wallpaper_orig";
- static final String WALLPAPER_CROP = "wallpaper";
- static final String WALLPAPER_LOCK_ORIG = "wallpaper_lock_orig";
- static final String WALLPAPER_LOCK_CROP = "wallpaper_lock";
- static final String WALLPAPER_INFO = "wallpaper_info.xml";
- private static final String RECORD_FILE = "decode_record";
- private static final String RECORD_LOCK_FILE = "decode_lock_record";
-
- // All the various per-user state files we need to be aware of
- private static final String[] sPerUserFiles = new String[] {
- WALLPAPER, WALLPAPER_CROP,
- WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP,
- WALLPAPER_INFO
- };
/**
* Observes the wallpaper for changes and notifies all IWallpaperServiceCallbacks
@@ -883,18 +876,15 @@
*/
private final SparseArray<SparseArray<RemoteCallbackList<IWallpaperManagerCallback>>>
mColorsChangedListeners;
+ // The currently bound home or home+lock wallpaper
protected WallpaperData mLastWallpaper;
+ // The currently bound lock screen only wallpaper, or null if none
+ protected WallpaperData mLastLockWallpaper;
private IWallpaperManagerCallback mKeyguardListener;
private boolean mWaitingForUnlock;
private boolean mShuttingDown;
/**
- * ID of the current wallpaper, changed every time anything sets a wallpaper.
- * This is used for external detection of wallpaper update activity.
- */
- private int mWallpaperId;
-
- /**
* Name of the component used to display bitmap wallpapers from either the gallery or
* built-in wallpapers.
*/
@@ -976,13 +966,6 @@
}
}
- int makeWallpaperIdLocked() {
- do {
- ++mWallpaperId;
- } while (mWallpaperId == 0);
- return mWallpaperId;
- }
-
private boolean supportsMultiDisplay(WallpaperConnection connection) {
if (connection != null) {
return connection.mInfo == null // This is image wallpaper
@@ -1852,11 +1835,9 @@
final TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG);
t.traceBegin("Wallpaper_selinux_restorecon-" + userId);
try {
- final File wallpaperDir = getWallpaperDir(userId);
- for (String filename : sPerUserFiles) {
- File f = new File(wallpaperDir, filename);
- if (f.exists()) {
- SELinux.restorecon(f);
+ for (File file: WallpaperUtils.getWallpaperFiles(userId)) {
+ if (file.exists()) {
+ SELinux.restorecon(file);
}
}
} finally {
@@ -1872,12 +1853,9 @@
void onRemoveUser(int userId) {
if (userId < 1) return;
- final File wallpaperDir = getWallpaperDir(userId);
synchronized (mLock) {
stopObserversLocked(userId);
- for (String filename : sPerUserFiles) {
- new File(wallpaperDir, filename).delete();
- }
+ WallpaperUtils.getWallpaperFiles(userId).forEach(File::delete);
mUserRestorecon.delete(userId);
}
}
@@ -2874,8 +2852,8 @@
setWallpaperComponent(name, UserHandle.getCallingUserId(), FLAG_SYSTEM);
}
- private void setWallpaperComponent(ComponentName name, @SetWallpaperFlags int which,
- int userId) {
+ @VisibleForTesting
+ void setWallpaperComponent(ComponentName name, @SetWallpaperFlags int which, int userId) {
userId = ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,
false /* all */, true /* full */, "changing live wallpaper", null /* pkg */);
checkPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT);
@@ -3096,14 +3074,19 @@
Slog.w(TAG, msg);
return false;
}
- if (wallpaper.userId == mCurrentUserId && mLastWallpaper != null
+ if (mEnableSeparateLockScreenEngine) {
+ maybeDetachLastWallpapers(wallpaper);
+ } else if (wallpaper.userId == mCurrentUserId && mLastWallpaper != null
&& !wallpaper.equals(mFallbackWallpaper)) {
detachWallpaperLocked(mLastWallpaper);
}
wallpaper.wallpaperComponent = componentName;
wallpaper.connection = newConn;
newConn.mReply = reply;
- if (wallpaper.userId == mCurrentUserId && !wallpaper.equals(mFallbackWallpaper)) {
+ if (mEnableSeparateLockScreenEngine) {
+ updateCurrentWallpapers(wallpaper);
+ } else if (wallpaper.userId == mCurrentUserId && !wallpaper.equals(
+ mFallbackWallpaper)) {
mLastWallpaper = wallpaper;
}
updateFallbackConnection();
@@ -3120,6 +3103,40 @@
return true;
}
+ // Updates tracking of the currently bound wallpapers. Assumes mEnableSeparateLockScreenEngine
+ // is true.
+ private void updateCurrentWallpapers(WallpaperData newWallpaper) {
+ if (newWallpaper.userId == mCurrentUserId && !newWallpaper.equals(mFallbackWallpaper)) {
+ if (newWallpaper.mWhich == (FLAG_SYSTEM | FLAG_LOCK)) {
+ mLastWallpaper = newWallpaper;
+ mLastLockWallpaper = null;
+ } else if (newWallpaper.mWhich == FLAG_SYSTEM) {
+ mLastWallpaper = newWallpaper;
+ } else if (newWallpaper.mWhich == FLAG_LOCK) {
+ mLastLockWallpaper = newWallpaper;
+ }
+ }
+ }
+
+ // Detaches previously bound wallpapers if no longer in use. Assumes
+ // mEnableSeparateLockScreenEngine is true.
+ private void maybeDetachLastWallpapers(WallpaperData newWallpaper) {
+ if (newWallpaper.userId != mCurrentUserId || newWallpaper.equals(mFallbackWallpaper)) {
+ return;
+ }
+ boolean homeUpdated = (newWallpaper.mWhich & FLAG_SYSTEM) != 0;
+ boolean lockUpdated = (newWallpaper.mWhich & FLAG_LOCK) != 0;
+ // This is the case where a home+lock wallpaper was changed to home-only, and the old
+ // home+lock became (static) or will become (live) lock-only.
+ boolean lockNeedsHomeWallpaper = mLastLockWallpaper == null && !lockUpdated;
+ if (mLastWallpaper != null && homeUpdated && !lockNeedsHomeWallpaper) {
+ detachWallpaperLocked(mLastWallpaper);
+ }
+ if (mLastLockWallpaper != null && lockUpdated) {
+ detachWallpaperLocked(mLastLockWallpaper);
+ }
+ }
+
private void detachWallpaperLocked(WallpaperData wallpaper) {
if (wallpaper.connection != null) {
if (wallpaper.connection.mReply != null) {
@@ -3150,7 +3167,12 @@
wallpaper.connection.mTryToRebindRunnable);
wallpaper.connection = null;
- if (wallpaper == mLastWallpaper) mLastWallpaper = null;
+ if (wallpaper == mLastWallpaper) {
+ mLastWallpaper = null;
+ }
+ if (wallpaper == mLastLockWallpaper) {
+ mLastLockWallpaper = null;
+ }
}
}
@@ -3624,8 +3646,8 @@
final int id = parser.getAttributeInt(null, "id", -1);
if (id != -1) {
wallpaper.wallpaperId = id;
- if (id > mWallpaperId) {
- mWallpaperId = id;
+ if (id > WallpaperUtils.getCurrentWallpaperId()) {
+ WallpaperUtils.setCurrentWallpaperId(id);
}
} else {
wallpaper.wallpaperId = makeWallpaperIdLocked();
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperUtils.java b/services/core/java/com/android/server/wallpaper/WallpaperUtils.java
index a9b8092..d0311e3 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperUtils.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperUtils.java
@@ -19,10 +19,68 @@
import android.os.Environment;
import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
class WallpaperUtils {
+ static final String WALLPAPER = "wallpaper_orig";
+ static final String WALLPAPER_CROP = "wallpaper";
+ static final String WALLPAPER_LOCK_ORIG = "wallpaper_lock_orig";
+ static final String WALLPAPER_LOCK_CROP = "wallpaper_lock";
+ static final String WALLPAPER_INFO = "wallpaper_info.xml";
+ static final String RECORD_FILE = "decode_record";
+ static final String RECORD_LOCK_FILE = "decode_lock_record";
+
+ // All the various per-user state files we need to be aware of
+ private static final String[] sPerUserFiles = new String[] {
+ WALLPAPER, WALLPAPER_CROP,
+ WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP,
+ WALLPAPER_INFO
+ };
+
+ /**
+ * ID of the current wallpaper, incremented every time anything sets a wallpaper.
+ * This is used for external detection of wallpaper update activity.
+ */
+ private static int sWallpaperId;
+
static File getWallpaperDir(int userId) {
return Environment.getUserSystemDirectory(userId);
}
+
+ /**
+ * generate a new wallpaper id
+ * should be called with the {@link WallpaperManagerService} lock held
+ */
+ static int makeWallpaperIdLocked() {
+ do {
+ ++sWallpaperId;
+ } while (sWallpaperId == 0);
+ return sWallpaperId;
+ }
+
+ /**
+ * returns the id of the current wallpaper (the last one that has been set)
+ */
+ static int getCurrentWallpaperId() {
+ return sWallpaperId;
+ }
+
+ /**
+ * sets the id of the current wallpaper
+ * used when a wallpaper with higher id than current is loaded from settings
+ */
+ static void setCurrentWallpaperId(int id) {
+ sWallpaperId = id;
+ }
+
+ static List<File> getWallpaperFiles(int userId) {
+ File wallpaperDir = getWallpaperDir(userId);
+ List<File> result = new ArrayList<File>();
+ for (int i = 0; i < sPerUserFiles.length; i++) {
+ result.add(new File(wallpaperDir, sPerUserFiles[i]));
+ }
+ return result;
+ }
}
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index e2ab216..65127e4 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -891,8 +891,7 @@
// to show the border. We will do so when the pending message is handled.
if (!mHandler.hasMessages(
MyHandler.MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED)) {
- setMagnifiedRegionBorderShown(
- isMagnifying() || isForceShowingMagnifiableBounds(), true);
+ setMagnifiedRegionBorderShown(isForceShowingMagnifiableBounds(), true);
}
}
@@ -1057,7 +1056,7 @@
// rotation or folding/unfolding the device. In the rotation case, the screenshot
// used for rotation already has the border. After the rotation is complete
// we will show the border.
- if (isMagnifying() || isForceShowingMagnifiableBounds()) {
+ if (isForceShowingMagnifiableBounds()) {
setMagnifiedRegionBorderShown(false, false);
final long delay = (long) (mLongAnimationDuration
* mService.getWindowAnimationScaleLocked());
@@ -1398,8 +1397,7 @@
case MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED : {
synchronized (mService.mGlobalLock) {
- if (mMagnifedViewport.isMagnifying()
- || isForceShowingMagnifiableBounds()) {
+ if (isForceShowingMagnifiableBounds()) {
mMagnifedViewport.setMagnifiedRegionBorderShown(true, true);
mService.scheduleAnimationLocked();
}
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java
index 4428be7..d4895ed 100644
--- a/services/core/java/com/android/server/wm/ActivityClientController.java
+++ b/services/core/java/com/android/server/wm/ActivityClientController.java
@@ -46,6 +46,7 @@
import static com.android.server.wm.ActivityRecord.State.PAUSING;
import static com.android.server.wm.ActivityRecord.State.RESTARTING_PROCESS;
import static com.android.server.wm.ActivityRecord.State.RESUMED;
+import static com.android.server.wm.ActivityRecord.State.STOPPING;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ALL;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
@@ -240,11 +241,21 @@
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityStopped");
r = ActivityRecord.isInRootTaskLocked(token);
if (r != null) {
+ if (!r.isState(STOPPING, RESTARTING_PROCESS)
+ && mTaskSupervisor.hasScheduledRestartTimeouts(r)) {
+ // Recover the restarting state which was replaced by other lifecycle changes.
+ r.setState(RESTARTING_PROCESS, "continue-restart");
+ }
if (r.attachedToProcess() && r.isState(RESTARTING_PROCESS)) {
// The activity was requested to restart from
// {@link #restartActivityProcessIfVisible}.
restartingName = r.app.mName;
restartingUid = r.app.mUid;
+ // Make EnsureActivitiesVisibleHelper#makeVisibleAndRestartIfNeeded not skip
+ // restarting non-top activity.
+ if (r != r.getTask().topRunningActivity()) {
+ r.setVisibleRequested(false);
+ }
}
r.activityStopped(icicle, persistentState, description);
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 9a7b165..6abd3d7 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -727,6 +727,7 @@
/**
* When set to true, the IME insets will be frozen until the next app becomes IME input target.
* @see InsetsPolicy#adjustVisibilityForIme
+ * @see ImeInsetsSourceProvider#updateClientVisibility
*/
boolean mImeInsetsFrozenUntilStartInput;
@@ -1576,7 +1577,6 @@
if (newParent != null) {
if (isState(RESUMED)) {
newParent.setResumedActivity(this, "onParentChanged");
- mImeInsetsFrozenUntilStartInput = false;
}
mLetterboxUiController.onActivityParentChanged(newParent);
}
@@ -8874,13 +8874,6 @@
}
}
- @Override
- void onResize() {
- // Reset freezing IME insets flag when the activity resized.
- mImeInsetsFrozenUntilStartInput = false;
- super.onResize();
- }
-
private boolean applyAspectRatio(Rect outBounds, Rect containingAppBounds,
Rect containingBounds) {
return applyAspectRatio(outBounds, containingAppBounds, containingBounds,
@@ -9364,6 +9357,15 @@
configChangeFlags = 0;
return;
}
+ if (!preserveWindow) {
+ // If the activity is the IME input target, ensure storing the last IME shown state
+ // before relaunching it for restoring the IME visibility once its new window focused.
+ final InputTarget imeInputTarget = mDisplayContent.getImeInputTarget();
+ mLastImeShown = imeInputTarget != null && imeInputTarget.getWindowState() != null
+ && imeInputTarget.getWindowState().mActivityRecord == this
+ && mDisplayContent.mInputMethodWindow != null
+ && mDisplayContent.mInputMethodWindow.isVisible();
+ }
// Do not waiting for translucent activity if it is going to relaunch.
final Task rootTask = getRootTask();
if (rootTask != null && rootTask.mTranslucentActivityWaiting == this) {
diff --git a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
index b40aa3c..1944b3f 100644
--- a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
@@ -284,7 +284,7 @@
IntentSender target = createIntentSenderForOriginalIntent(mCallingUid,
FLAG_CANCEL_CURRENT | FLAG_ONE_SHOT);
- mIntent = UnlaunchableAppActivity.createInQuietModeDialogIntent(mUserId, target);
+ mIntent = UnlaunchableAppActivity.createInQuietModeDialogIntent(mUserId, target, mRInfo);
mCallingPid = mRealCallingPid;
mCallingUid = mRealCallingUid;
mResolvedType = null;
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index 407ffd0..919bab8 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -2297,6 +2297,10 @@
mHandler.sendEmptyMessageDelayed(SLEEP_TIMEOUT_MSG, SLEEP_TIMEOUT);
}
+ boolean hasScheduledRestartTimeouts(ActivityRecord r) {
+ return mHandler.hasMessages(RESTART_ACTIVITY_PROCESS_TIMEOUT_MSG, r);
+ }
+
void removeRestartTimeouts(ActivityRecord r) {
mHandler.removeMessages(RESTART_ACTIVITY_PROCESS_TIMEOUT_MSG, r);
}
diff --git a/services/core/java/com/android/server/wm/ContentRecorder.java b/services/core/java/com/android/server/wm/ContentRecorder.java
index af135b7..9e258cb 100644
--- a/services/core/java/com/android/server/wm/ContentRecorder.java
+++ b/services/core/java/com/android/server/wm/ContentRecorder.java
@@ -20,6 +20,7 @@
import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
import static android.view.ContentRecordingSession.RECORD_CONTENT_DISPLAY;
import static android.view.ContentRecordingSession.RECORD_CONTENT_TASK;
+import static android.view.ViewProtoEnums.DISPLAY_STATE_OFF;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONTENT_RECORDING;
@@ -317,6 +318,11 @@
if (mContentRecordingSession.getContentToRecord() == RECORD_CONTENT_TASK) {
mMediaProjectionManager.notifyActiveProjectionCapturedContentVisibilityChanged(
mRecordedWindowContainer.asTask().isVisibleRequested());
+ } else {
+ int currentDisplayState =
+ mRecordedWindowContainer.asDisplayContent().getDisplay().getState();
+ mMediaProjectionManager.notifyActiveProjectionCapturedContentVisibilityChanged(
+ currentDisplayState != DISPLAY_STATE_OFF);
}
// No need to clean up. In SurfaceFlinger, parents hold references to their children. The
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index e7a5ee7..0d6c8db 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -4509,11 +4509,35 @@
mImeWindowsContainer.getParent().mSurfaceControl));
updateImeControlTarget(forceUpdateImeParent);
}
- // Unfreeze IME insets after the new target updated, in case updateAboveInsetsState may
- // deliver unrelated IME insets change to the non-IME requester.
- if (target != null) {
- target.unfreezeInsetsAfterStartInput();
+ }
+
+ /**
+ * Callback from {@link ImeInsetsSourceProvider#updateClientVisibility} for the system to
+ * judge whether or not to notify the IME insets provider to dispatch this reported IME client
+ * visibility state to the app clients when needed.
+ */
+ boolean onImeInsetsClientVisibilityUpdate() {
+ boolean[] changed = new boolean[1];
+
+ // Unlike the IME layering target or the control target can be updated during the layout
+ // change, the IME input target requires to be changed after gaining the input focus.
+ // In case unfreezing IME insets state may too early during IME focus switching, we unfreeze
+ // when activities going to be visible until the input target changed, or the
+ // activity was the current input target that has to unfreeze after updating the IME
+ // client visibility.
+ final ActivityRecord inputTargetActivity =
+ mImeInputTarget != null ? mImeInputTarget.getActivityRecord() : null;
+ final boolean targetChanged = mImeInputTarget != mLastImeInputTarget;
+ if (targetChanged || inputTargetActivity != null && inputTargetActivity.isVisibleRequested()
+ && inputTargetActivity.mImeInsetsFrozenUntilStartInput) {
+ forAllActivities(r -> {
+ if (r.mImeInsetsFrozenUntilStartInput && r.isVisibleRequested()) {
+ r.mImeInsetsFrozenUntilStartInput = false;
+ changed[0] = true;
+ }
+ });
}
+ return changed[0];
}
void updateImeControlTarget() {
@@ -6817,12 +6841,12 @@
public void showInsets(@WindowInsets.Type.InsetsType int types, boolean fromIme,
@Nullable ImeTracker.Token statsToken) {
try {
- ImeTracker.get().onProgress(statsToken,
+ ImeTracker.forLogging().onProgress(statsToken,
ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROL_TARGET_SHOW_INSETS);
mRemoteInsetsController.showInsets(types, fromIme, statsToken);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to deliver showInsets", e);
- ImeTracker.get().onFailed(statsToken,
+ ImeTracker.forLogging().onFailed(statsToken,
ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROL_TARGET_SHOW_INSETS);
}
}
@@ -6831,12 +6855,12 @@
public void hideInsets(@InsetsType int types, boolean fromIme,
@Nullable ImeTracker.Token statsToken) {
try {
- ImeTracker.get().onProgress(statsToken,
+ ImeTracker.forLogging().onProgress(statsToken,
ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROL_TARGET_HIDE_INSETS);
mRemoteInsetsController.hideInsets(types, fromIme, statsToken);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to deliver hideInsets", e);
- ImeTracker.get().onFailed(statsToken,
+ ImeTracker.forLogging().onFailed(statsToken,
ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROL_TARGET_HIDE_INSETS);
}
}
diff --git a/services/core/java/com/android/server/wm/EmbeddedWindowController.java b/services/core/java/com/android/server/wm/EmbeddedWindowController.java
index d54f77a..c3c727a 100644
--- a/services/core/java/com/android/server/wm/EmbeddedWindowController.java
+++ b/services/core/java/com/android/server/wm/EmbeddedWindowController.java
@@ -335,10 +335,6 @@
}
@Override
- public void unfreezeInsetsAfterStartInput() {
- }
-
- @Override
public InsetsControlTarget getImeControlTarget() {
return mWmService.getDefaultDisplayContentLocked().mRemoteInsetsControlTarget;
}
diff --git a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
index 90d0f16..60e2e95 100644
--- a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
@@ -140,10 +140,14 @@
@Override
protected boolean updateClientVisibility(InsetsControlTarget caller) {
+ if (caller != getControlTarget()) {
+ return false;
+ }
boolean changed = super.updateClientVisibility(caller);
if (changed && caller.isRequestedVisible(mSource.getType())) {
reportImeDrawnForOrganizer(caller);
}
+ changed |= mDisplayContent.onImeInsetsClientVisibilityUpdate();
return changed;
}
@@ -178,7 +182,8 @@
boolean targetChanged = isTargetChangedWithinActivity(imeTarget);
mImeRequester = imeTarget;
// There was still a stats token, so that request presumably failed.
- ImeTracker.get().onFailed(mImeRequesterStatsToken, ImeTracker.PHASE_WM_SHOW_IME_RUNNER);
+ ImeTracker.forLogging().onFailed(
+ mImeRequesterStatsToken, ImeTracker.PHASE_WM_SHOW_IME_RUNNER);
mImeRequesterStatsToken = statsToken;
if (targetChanged) {
// target changed, check if new target can show IME.
@@ -193,12 +198,12 @@
ProtoLog.d(WM_DEBUG_IME, "Schedule IME show for %s", mImeRequester.getWindow() == null
? mImeRequester : mImeRequester.getWindow().getName());
mShowImeRunner = () -> {
- ImeTracker.get().onProgress(mImeRequesterStatsToken,
+ ImeTracker.forLogging().onProgress(mImeRequesterStatsToken,
ImeTracker.PHASE_WM_SHOW_IME_RUNNER);
ProtoLog.d(WM_DEBUG_IME, "Run showImeRunner");
// Target should still be the same.
if (isReadyToShowIme()) {
- ImeTracker.get().onProgress(mImeRequesterStatsToken,
+ ImeTracker.forLogging().onProgress(mImeRequesterStatsToken,
ImeTracker.PHASE_WM_SHOW_IME_READY);
final InsetsControlTarget target = mDisplayContent.getImeTarget(IME_TARGET_CONTROL);
@@ -215,7 +220,7 @@
? mImeRequester.getWindow().getName() : ""));
}
} else {
- ImeTracker.get().onFailed(mImeRequesterStatsToken,
+ ImeTracker.forLogging().onFailed(mImeRequesterStatsToken,
ImeTracker.PHASE_WM_SHOW_IME_READY);
}
// Clear token here so we don't report an error in abortShowImePostLayout().
@@ -254,7 +259,8 @@
mImeRequester = null;
mIsImeLayoutDrawn = false;
mShowImeRunner = null;
- ImeTracker.get().onCancelled(mImeRequesterStatsToken, ImeTracker.PHASE_WM_SHOW_IME_RUNNER);
+ ImeTracker.forLogging().onCancelled(
+ mImeRequesterStatsToken, ImeTracker.PHASE_WM_SHOW_IME_RUNNER);
mImeRequesterStatsToken = null;
}
diff --git a/services/core/java/com/android/server/wm/InputTarget.java b/services/core/java/com/android/server/wm/InputTarget.java
index b5ab62b..653f5f5 100644
--- a/services/core/java/com/android/server/wm/InputTarget.java
+++ b/services/core/java/com/android/server/wm/InputTarget.java
@@ -16,8 +16,8 @@
package com.android.server.wm;
-import android.view.IWindow;
import android.util.proto.ProtoOutputStream;
+import android.view.IWindow;
/**
* Common interface between focusable objects.
@@ -58,7 +58,6 @@
boolean canScreenshotIme();
ActivityRecord getActivityRecord();
- void unfreezeInsetsAfterStartInput();
boolean isInputMethodClientFocus(int uid, int pid);
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index 1df534f..874f942 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -707,7 +707,8 @@
InsetsPolicyAnimationControlListener(boolean show, Runnable finishCallback, int types) {
super(show, false /* hasCallbacks */, types, BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE,
- false /* disable */, 0 /* floatingImeBottomInsets */, null);
+ false /* disable */, 0 /* floatingImeBottomInsets */,
+ null /* loggingListener */, null /* jankContext */);
mFinishCallback = finishCallback;
mControlCallbacks = new InsetsPolicyAnimationControlCallbacks(this);
}
diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java
index 75ba214..9c43c1d 100644
--- a/services/core/java/com/android/server/wm/LetterboxUiController.java
+++ b/services/core/java/com/android/server/wm/LetterboxUiController.java
@@ -1146,10 +1146,9 @@
final ActivityRecord firstOpaqueActivityBeneath = mActivityRecord.getTask().getActivity(
ActivityRecord::fillsParent, mActivityRecord, false /* includeBoundary */,
true /* traverseTopToBottom */);
- if (firstOpaqueActivityBeneath == null
- || mActivityRecord.launchedFromUid != firstOpaqueActivityBeneath.getUid()) {
+ if (firstOpaqueActivityBeneath == null) {
// We skip letterboxing if the translucent activity doesn't have any opaque
- // activities beneath of if it's launched from a different user (e.g. notification)
+ // activities beneath
return;
}
inheritConfiguration(firstOpaqueActivityBeneath);
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index d395f12..db88f0f 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -36,7 +36,6 @@
import android.animation.ArgbEvaluator;
import android.content.Context;
import android.graphics.Color;
-import android.graphics.GraphicBuffer;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.Rect;
@@ -251,9 +250,6 @@
screenshotBuffer.getColorSpace());
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
- GraphicBuffer buffer = GraphicBuffer.createFromHardwareBuffer(
- screenshotBuffer.getHardwareBuffer());
-
t.setLayer(mScreenshotLayer, SCREEN_FREEZE_LAYER_BASE);
t.reparent(mBackColorSurface, displayContent.getSurfaceControl());
// If hdr layers are on-screen, e.g. picture-in-picture mode, the screenshot of
@@ -263,10 +259,11 @@
t.setLayer(mBackColorSurface, -1);
t.setColor(mBackColorSurface, new float[]{mStartLuma, mStartLuma, mStartLuma});
t.setAlpha(mBackColorSurface, 1);
- t.setBuffer(mScreenshotLayer, buffer);
+ t.setBuffer(mScreenshotLayer, hardwareBuffer);
t.setColorSpace(mScreenshotLayer, screenshotBuffer.getColorSpace());
t.show(mScreenshotLayer);
t.show(mBackColorSurface);
+ hardwareBuffer.close();
if (mRoundedCornerOverlay != null) {
for (SurfaceControl sc : mRoundedCornerOverlay) {
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index a3827c0..db17ae1 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -1958,7 +1958,8 @@
}
boolean shouldSleepActivities() {
- return false;
+ final Task task = getRootTask();
+ return task != null && task.shouldSleepActivities();
}
@Override
diff --git a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
index 5f186a1..a27cc3a 100644
--- a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
@@ -541,9 +541,12 @@
synchronized (mGlobalLock) {
final TaskFragmentOrganizerState organizerState =
mTaskFragmentOrganizerState.get(organizer.asBinder());
- return organizerState != null
- ? organizerState.mRemoteAnimationDefinition
- : null;
+ if (organizerState == null) {
+ Slog.e(TAG, "TaskFragmentOrganizer has been unregistered or died when trying"
+ + " to play animation on its organized windows.");
+ return null;
+ }
+ return organizerState.mRemoteAnimationDefinition;
}
}
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 5e081d5..e538584 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -2406,7 +2406,7 @@
if (isDisplayRotation) {
// This isn't cheap, so only do it for display rotations.
changeInfo.mSnapshotLuma = TransitionAnimation.getBorderLuma(
- screenshotBuffer.getHardwareBuffer(), screenshotBuffer.getColorSpace());
+ buffer, screenshotBuffer.getColorSpace());
}
SurfaceControl.Transaction t = wc.mWmService.mTransactionFactory.get();
@@ -2418,6 +2418,7 @@
t.setLayer(snapshotSurface, Integer.MAX_VALUE);
t.apply();
t.close();
+ buffer.close();
// Detach the screenshot on the sync transaction (the screenshot is just meant to
// freeze the window until the sync transaction is applied (with all its other
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 4e7613b..5adae41 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -8071,14 +8071,14 @@
dc.getInsetsStateController().getImeSourceProvider().abortShowImePostLayout();
}
if (dc != null && dc.getImeTarget(IME_TARGET_CONTROL) != null) {
- ImeTracker.get().onProgress(statsToken,
+ ImeTracker.forLogging().onProgress(statsToken,
ImeTracker.PHASE_WM_HAS_IME_INSETS_CONTROL_TARGET);
ProtoLog.d(WM_DEBUG_IME, "hideIme Control target: %s ",
dc.getImeTarget(IME_TARGET_CONTROL));
dc.getImeTarget(IME_TARGET_CONTROL).hideInsets(WindowInsets.Type.ime(),
true /* fromIme */, statsToken);
} else {
- ImeTracker.get().onFailed(statsToken,
+ ImeTracker.forLogging().onFailed(statsToken,
ImeTracker.PHASE_WM_HAS_IME_INSETS_CONTROL_TARGET);
}
if (dc != null) {
@@ -9177,6 +9177,7 @@
boolean shouldRestoreImeVisibility(IBinder imeTargetWindowToken) {
final Task imeTargetWindowTask;
+ boolean hadRequestedShowIme = false;
synchronized (mGlobalLock) {
final WindowState imeTargetWindow = mWindowMap.get(imeTargetWindowToken);
if (imeTargetWindow == null) {
@@ -9186,11 +9187,14 @@
if (imeTargetWindowTask == null) {
return false;
}
+ if (imeTargetWindow.mActivityRecord != null) {
+ hadRequestedShowIme = imeTargetWindow.mActivityRecord.mLastImeShown;
+ }
}
final TaskSnapshot snapshot = getTaskSnapshot(imeTargetWindowTask.mTaskId,
imeTargetWindowTask.mUserId, false /* isLowResolution */,
false /* restoreFromDisk */);
- return snapshot != null && snapshot.hasImeSurface();
+ return snapshot != null && snapshot.hasImeSurface() || hadRequestedShowIme;
}
@Override
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index dd70fca..6a1adb4 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -21,6 +21,7 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOW_CONFIG_BOUNDS;
import static android.view.Display.DEFAULT_DISPLAY;
+import static android.window.TaskFragmentOperation.OP_TYPE_CLEAR_ADJACENT_TASK_FRAGMENTS;
import static android.window.TaskFragmentOperation.OP_TYPE_CREATE_TASK_FRAGMENT;
import static android.window.TaskFragmentOperation.OP_TYPE_DELETE_TASK_FRAGMENT;
import static android.window.TaskFragmentOperation.OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT;
@@ -1167,34 +1168,50 @@
}
case OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS: {
final IBinder secondaryFragmentToken = operation.getSecondaryFragmentToken();
- final TaskFragment secondaryTaskFragment = secondaryFragmentToken != null
- ? mLaunchTaskFragments.get(secondaryFragmentToken)
- : null;
- taskFragment.setAdjacentTaskFragment(secondaryTaskFragment);
- effects |= TRANSACT_EFFECTS_LIFECYCLE;
-
- // Clear the focused app if the focused app is no longer visible after reset the
- // adjacent TaskFragments.
- if (secondaryTaskFragment == null
- && taskFragment.getDisplayContent().mFocusedApp != null
- && taskFragment.hasChild(taskFragment.getDisplayContent().mFocusedApp)
- && !taskFragment.shouldBeVisible(null /* starting */)) {
- taskFragment.getDisplayContent().setFocusedApp(null);
+ final TaskFragment secondaryTaskFragment =
+ mLaunchTaskFragments.get(secondaryFragmentToken);
+ if (secondaryTaskFragment == null) {
+ final Throwable exception = new IllegalArgumentException(
+ "SecondaryFragmentToken must be set for setAdjacentTaskFragments.");
+ sendTaskFragmentOperationFailure(organizer, errorCallbackToken, taskFragment,
+ opType, exception);
+ break;
+ }
+ if (taskFragment.getAdjacentTaskFragment() != secondaryTaskFragment) {
+ // Only have lifecycle effect if the adjacent changed.
+ taskFragment.setAdjacentTaskFragment(secondaryTaskFragment);
+ effects |= TRANSACT_EFFECTS_LIFECYCLE;
}
final Bundle bundle = hop.getLaunchOptions();
final WindowContainerTransaction.TaskFragmentAdjacentParams adjacentParams =
- bundle != null ? new WindowContainerTransaction.TaskFragmentAdjacentParams(
- bundle) : null;
- if (adjacentParams == null) {
+ bundle != null
+ ? new WindowContainerTransaction.TaskFragmentAdjacentParams(bundle)
+ : null;
+ taskFragment.setDelayLastActivityRemoval(adjacentParams != null
+ && adjacentParams.shouldDelayPrimaryLastActivityRemoval());
+ secondaryTaskFragment.setDelayLastActivityRemoval(adjacentParams != null
+ && adjacentParams.shouldDelaySecondaryLastActivityRemoval());
+ break;
+ }
+ case OP_TYPE_CLEAR_ADJACENT_TASK_FRAGMENTS: {
+ final TaskFragment adjacentTaskFragment = taskFragment.getAdjacentTaskFragment();
+ if (adjacentTaskFragment == null) {
break;
}
+ taskFragment.resetAdjacentTaskFragment();
+ effects |= TRANSACT_EFFECTS_LIFECYCLE;
- taskFragment.setDelayLastActivityRemoval(
- adjacentParams.shouldDelayPrimaryLastActivityRemoval());
- if (secondaryTaskFragment != null) {
- secondaryTaskFragment.setDelayLastActivityRemoval(
- adjacentParams.shouldDelaySecondaryLastActivityRemoval());
+ // Clear the focused app if the focused app is no longer visible after reset the
+ // adjacent TaskFragments.
+ final ActivityRecord focusedApp = taskFragment.getDisplayContent().mFocusedApp;
+ final TaskFragment focusedTaskFragment = focusedApp != null
+ ? focusedApp.getTaskFragment()
+ : null;
+ if ((focusedTaskFragment == taskFragment
+ || focusedTaskFragment == adjacentTaskFragment)
+ && !focusedTaskFragment.shouldBeVisible(null /* starting */)) {
+ focusedTaskFragment.getDisplayContent().setFocusedApp(null /* newFocus */);
}
break;
}
@@ -1528,6 +1545,9 @@
throw new IllegalArgumentException("setAdjacentRootsHierarchyOp: Not created by"
+ " organizer root1=" + root1 + " root2=" + root2);
}
+ if (root1.getAdjacentTaskFragment() == root2) {
+ return TRANSACT_EFFECTS_NONE;
+ }
root1.setAdjacentTaskFragment(root2);
return TRANSACT_EFFECTS_LIFECYCLE;
}
@@ -1538,7 +1558,9 @@
throw new IllegalArgumentException("clearAdjacentRootsHierarchyOp: Not created by"
+ " organizer root=" + root);
}
-
+ if (root.getAdjacentTaskFragment() == null) {
+ return TRANSACT_EFFECTS_NONE;
+ }
root.resetAdjacentTaskFragment();
return TRANSACT_EFFECTS_LIFECYCLE;
}
@@ -1910,6 +1932,8 @@
ownerTask.addChild(taskFragment, position);
taskFragment.setWindowingMode(creationParams.getWindowingMode());
taskFragment.setBounds(creationParams.getInitialBounds());
+ // Record the initial relative embedded bounds.
+ taskFragment.updateRelativeEmbeddedBounds();
mLaunchTaskFragments.put(creationParams.getFragmentToken(), taskFragment);
if (transition != null) transition.collectExistenceChange(taskFragment);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index a41d350..7a0070b 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -388,14 +388,6 @@
int mPrepareSyncSeqId = 0;
/**
- * {@code true} when the client was still drawing for sync when the sync-set was finished or
- * cancelled. This can happen if the window goes away during a sync. In this situation we need
- * to make sure to still apply the postDrawTransaction when it finishes to prevent the client
- * from getting stuck in a bad state.
- */
- boolean mClientWasDrawingForSync = false;
-
- /**
* Special mode that is intended only for the rounded corner overlay: during rotation
* transition, we un-rotate the window token such that the window appears as it did before the
* rotation.
@@ -4001,12 +3993,12 @@
public void showInsets(@InsetsType int types, boolean fromIme,
@Nullable ImeTracker.Token statsToken) {
try {
- ImeTracker.get().onProgress(statsToken,
+ ImeTracker.forLogging().onProgress(statsToken,
ImeTracker.PHASE_WM_WINDOW_INSETS_CONTROL_TARGET_SHOW_INSETS);
mClient.showInsets(types, fromIme, statsToken);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to deliver showInsets", e);
- ImeTracker.get().onFailed(statsToken,
+ ImeTracker.forLogging().onFailed(statsToken,
ImeTracker.PHASE_WM_WINDOW_INSETS_CONTROL_TARGET_SHOW_INSETS);
}
}
@@ -4015,12 +4007,12 @@
public void hideInsets(@InsetsType int types, boolean fromIme,
@Nullable ImeTracker.Token statsToken) {
try {
- ImeTracker.get().onProgress(statsToken,
+ ImeTracker.forLogging().onProgress(statsToken,
ImeTracker.PHASE_WM_WINDOW_INSETS_CONTROL_TARGET_HIDE_INSETS);
mClient.hideInsets(types, fromIme, statsToken);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to deliver hideInsets", e);
- ImeTracker.get().onFailed(statsToken,
+ ImeTracker.forLogging().onFailed(statsToken,
ImeTracker.PHASE_WM_WINDOW_INSETS_CONTROL_TARGET_HIDE_INSETS);
}
}
@@ -5977,9 +5969,6 @@
@Override
void finishSync(Transaction outMergedTransaction, boolean cancel) {
- if (mSyncState == SYNC_STATE_WAITING_FOR_DRAW && mRedrawForSyncReported) {
- mClientWasDrawingForSync = true;
- }
mPrepareSyncSeqId = 0;
if (cancel) {
// This is leaving sync so any buffers left in the sync have a chance of
@@ -6047,9 +6036,7 @@
layoutNeeded = onSyncFinishedDrawing();
}
- layoutNeeded |=
- mWinAnimator.finishDrawingLocked(postDrawTransaction, mClientWasDrawingForSync);
- mClientWasDrawingForSync = false;
+ layoutNeeded |= mWinAnimator.finishDrawingLocked(postDrawTransaction);
// We always want to force a traversal after a finish draw for blast sync.
return !skipLayout && (hasSyncHandlers || layoutNeeded);
}
@@ -6267,13 +6254,6 @@
}
@Override
- public void unfreezeInsetsAfterStartInput() {
- if (mActivityRecord != null) {
- mActivityRecord.mImeInsetsFrozenUntilStartInput = false;
- }
- }
-
- @Override
public boolean isInputMethodClientFocus(int uid, int pid) {
return getDisplayContent().isInputMethodClientFocus(uid, pid);
}
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index a1f4096..a102986 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -151,17 +151,6 @@
int mAttrType;
- /**
- * Handles surface changes synchronized to after the client has drawn the surface. This
- * transaction is currently used to reparent the old surface children to the new surface once
- * the client has completed drawing to the new surface.
- * This transaction is also used to merge transactions parceled in by the client. The client
- * uses the transaction to update the relative z of its children from the old parent surface
- * to the new parent surface once window manager reparents its children.
- */
- private final SurfaceControl.Transaction mPostDrawTransaction =
- new SurfaceControl.Transaction();
-
WindowStateAnimator(final WindowState win) {
final WindowManagerService service = win.mWmService;
@@ -217,8 +206,7 @@
}
}
- boolean finishDrawingLocked(SurfaceControl.Transaction postDrawTransaction,
- boolean forceApplyNow) {
+ boolean finishDrawingLocked(SurfaceControl.Transaction postDrawTransaction) {
final boolean startingWindow =
mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
if (startingWindow) {
@@ -240,14 +228,7 @@
}
if (postDrawTransaction != null) {
- // If there is no surface, the last draw was for the previous surface. We don't want to
- // wait until the new surface is shown and instead just apply the transaction right
- // away.
- if (mLastHidden && mDrawState != NO_SURFACE && !forceApplyNow) {
- mPostDrawTransaction.merge(postDrawTransaction);
- } else {
- mWin.getSyncTransaction().merge(postDrawTransaction);
- }
+ mWin.getSyncTransaction().merge(postDrawTransaction);
layoutNeeded = true;
}
@@ -543,7 +524,6 @@
if (!shown)
return false;
- t.merge(mPostDrawTransaction);
return true;
}
@@ -710,10 +690,6 @@
}
void destroySurface(SurfaceControl.Transaction t) {
- // Since the SurfaceControl is getting torn down, it's safe to just clean up any
- // pending transactions that were in mPostDrawTransaction, as well.
- t.merge(mPostDrawTransaction);
-
try {
if (mSurfaceController != null) {
mSurfaceController.destroy(t);
diff --git a/services/credentials/java/com/android/server/credentials/ClearRequestSession.java b/services/credentials/java/com/android/server/credentials/ClearRequestSession.java
index 2141d51..be60946 100644
--- a/services/credentials/java/com/android/server/credentials/ClearRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/ClearRequestSession.java
@@ -39,15 +39,17 @@
implements ProviderSession.ProviderInternalCallback<Void> {
private static final String TAG = "GetRequestSession";
- public ClearRequestSession(Context context, int userId,
+ public ClearRequestSession(Context context, int userId, int callingUid,
IClearCredentialStateCallback callback, ClearCredentialStateRequest request,
CallingAppInfo callingAppInfo) {
- super(context, userId, request, callback, RequestInfo.TYPE_UNDEFINED, callingAppInfo);
+ super(context, userId, callingUid, request, callback, RequestInfo.TYPE_UNDEFINED,
+ callingAppInfo);
}
/**
* Creates a new provider session, and adds it list of providers that are contributing to
* this session.
+ *
* @return the provider session created within this request session, for the given provider
* info.
*/
@@ -84,14 +86,12 @@
respondToClientWithResponseAndFinish();
}
- @Override
protected void onProviderResponseComplete(ComponentName componentName) {
if (!isAnyProviderPending()) {
onFinalResponseReceived(componentName, null);
}
}
- @Override
protected void onProviderTerminated(ComponentName componentName) {
if (!isAnyProviderPending()) {
processResponses();
@@ -113,8 +113,10 @@
Log.i(TAG, "respondToClientWithResponseAndFinish");
try {
mClientCallback.onSuccess();
+ logApiCalled(RequestType.CLEAR_CREDENTIALS, /* isSuccessful */ true);
} catch (RemoteException e) {
Log.i(TAG, "Issue while propagating the response to the client");
+ logApiCalled(RequestType.CLEAR_CREDENTIALS, /* isSuccessful */ false);
}
finishSession();
}
@@ -126,10 +128,12 @@
} catch (RemoteException e) {
e.printStackTrace();
}
+ logApiCalled(RequestType.CLEAR_CREDENTIALS, /* isSuccessful */ false);
finishSession();
}
+
private void processResponses() {
- for (ProviderSession session: mProviders.values()) {
+ for (ProviderSession session : mProviders.values()) {
if (session.isProviderResponseSet()) {
// If even one provider responded successfully, send back the response
// TODO: Aggregate other exceptions
@@ -138,6 +142,6 @@
}
}
// TODO: Replace with properly defined error type
- respondToClientWithErrorAndFinish("unknown", "All providers failed");
+ respondToClientWithErrorAndFinish("UNKNOWN", "All providers failed");
}
}
diff --git a/services/credentials/java/com/android/server/credentials/CreateRequestSession.java b/services/credentials/java/com/android/server/credentials/CreateRequestSession.java
index 3091c0a..acfa491 100644
--- a/services/credentials/java/com/android/server/credentials/CreateRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/CreateRequestSession.java
@@ -20,6 +20,7 @@
import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Context;
+import android.credentials.CreateCredentialException;
import android.credentials.CreateCredentialRequest;
import android.credentials.CreateCredentialResponse;
import android.credentials.CredentialManager;
@@ -43,11 +44,12 @@
implements ProviderSession.ProviderInternalCallback<CreateCredentialResponse> {
private static final String TAG = "CreateRequestSession";
- CreateRequestSession(@NonNull Context context, int userId,
+ CreateRequestSession(@NonNull Context context, int userId, int callingUid,
CreateCredentialRequest request,
ICreateCredentialCallback callback,
CallingAppInfo callingAppInfo) {
- super(context, userId, request, callback, RequestInfo.TYPE_CREATE, callingAppInfo);
+ super(context, userId, callingUid, request, callback, RequestInfo.TYPE_CREATE,
+ callingAppInfo);
}
/**
@@ -62,7 +64,7 @@
RemoteCredentialService remoteCredentialService) {
ProviderCreateSession providerCreateSession = ProviderCreateSession
.createNewSession(mContext, mUserId, providerInfo,
- this, remoteCredentialService);
+ this, remoteCredentialService);
if (providerCreateSession != null) {
Log.i(TAG, "In startProviderSession - provider session created and being added");
mProviders.put(providerCreateSession.getComponentName().flattenToString(),
@@ -80,26 +82,20 @@
mClientAppInfo.getPackageName()),
providerDataList));
} catch (RemoteException e) {
- Log.i(TAG, "Issue with invoking pending intent: " + e.getMessage());
- // TODO: Propagate failure
+ respondToClientWithErrorAndFinish(
+ CreateCredentialException.TYPE_UNKNOWN,
+ "Unable to invoke selector");
}
}
@Override
- public void onProviderStatusChanged(ProviderSession.Status status,
- ComponentName componentName) {
- super.onProviderStatusChanged(status, componentName);
- }
-
- @Override
public void onFinalResponseReceived(ComponentName componentName,
@Nullable CreateCredentialResponse response) {
Log.i(TAG, "onFinalCredentialReceived from: " + componentName.flattenToString());
if (response != null) {
respondToClientWithResponseAndFinish(response);
} else {
- // TODO("Replace with properly defined error type)
- respondToClientWithErrorAndFinish("unknown_type",
+ respondToClientWithErrorAndFinish(CreateCredentialException.TYPE_NO_CREDENTIAL,
"Invalid response");
}
}
@@ -112,8 +108,7 @@
@Override
public void onUiCancellation() {
- // TODO("Replace with properly defined error type")
- respondToClientWithErrorAndFinish("user_cancelled",
+ respondToClientWithErrorAndFinish(CreateCredentialException.TYPE_USER_CANCELED,
"User cancelled the selector");
}
@@ -121,8 +116,10 @@
Log.i(TAG, "respondToClientWithResponseAndFinish");
try {
mClientCallback.onResponse(response);
+ logApiCalled(RequestType.CREATE_CREDENTIALS, /* isSuccessful */ true);
} catch (RemoteException e) {
Log.i(TAG, "Issue while responding to client: " + e.getMessage());
+ logApiCalled(RequestType.CREATE_CREDENTIALS, /* isSuccessful */ false);
}
finishSession();
}
@@ -134,6 +131,25 @@
} catch (RemoteException e) {
Log.i(TAG, "Issue while responding to client: " + e.getMessage());
}
+ logApiCalled(RequestType.CREATE_CREDENTIALS, /* isSuccessful */ false);
finishSession();
}
+
+ @Override
+ public void onProviderStatusChanged(ProviderSession.Status status,
+ ComponentName componentName) {
+ Log.i(TAG, "in onProviderStatusChanged with status: " + status);
+ // If all provider responses have been received, we can either need the UI,
+ // or we need to respond with error. The only other case is the entry being
+ // selected after the UI has been invoked which has a separate code path.
+ if (!isAnyProviderPending()) {
+ if (isUiInvocationNeeded()) {
+ Log.i(TAG, "in onProviderStatusChanged - isUiInvocationNeeded");
+ getProviderDataAndInitiateUi();
+ } else {
+ respondToClientWithErrorAndFinish(CreateCredentialException.TYPE_NO_CREDENTIAL,
+ "No credentials available");
+ }
+ }
+ }
}
diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
index fa7661da..f76cf49 100644
--- a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
+++ b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
@@ -26,7 +26,9 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.credentials.ClearCredentialStateRequest;
+import android.credentials.CreateCredentialException;
import android.credentials.CreateCredentialRequest;
+import android.credentials.GetCredentialException;
import android.credentials.GetCredentialOption;
import android.credentials.GetCredentialRequest;
import android.credentials.IClearCredentialStateCallback;
@@ -267,11 +269,13 @@
ICancellationSignal cancelTransport = CancellationSignal.createTransport();
int userId = UserHandle.getCallingUserId();
+ int callingUid = Binder.getCallingUid();
// New request session, scoped for this request only.
final GetRequestSession session =
new GetRequestSession(
getContext(),
userId,
+ callingUid,
callback,
request,
constructCallingAppInfo(callingPackage, userId));
@@ -286,8 +290,8 @@
if (providerSessions.isEmpty()) {
try {
- // TODO("Replace with properly defined error type")
- callback.onError("unknown_type", "No providers available to fulfill request.");
+ callback.onError(GetCredentialException.TYPE_NO_CREDENTIAL,
+ "No credentials available on this device.");
} catch (RemoteException e) {
Log.i(
TAG,
@@ -317,10 +321,12 @@
// New request session, scoped for this request only.
int userId = UserHandle.getCallingUserId();
+ int callingUid = Binder.getCallingUid();
final CreateRequestSession session =
new CreateRequestSession(
getContext(),
userId,
+ callingUid,
request,
callback,
constructCallingAppInfo(callingPackage, userId));
@@ -331,8 +337,8 @@
if (providerSessions.isEmpty()) {
try {
- // TODO("Replace with properly defined error type")
- callback.onError("unknown_type", "No providers available to fulfill request.");
+ callback.onError(CreateCredentialException.TYPE_NO_CREDENTIAL,
+ "No credentials available on this device.");
} catch (RemoteException e) {
Log.i(
TAG,
@@ -432,10 +438,12 @@
// New request session, scoped for this request only.
int userId = UserHandle.getCallingUserId();
+ int callingUid = Binder.getCallingUid();
final ClearRequestSession session =
new ClearRequestSession(
getContext(),
userId,
+ callingUid,
callback,
request,
constructCallingAppInfo(callingPackage, userId));
@@ -447,7 +455,8 @@
if (providerSessions.isEmpty()) {
try {
// TODO("Replace with properly defined error type")
- callback.onError("unknown_type", "No providers available to fulfill request.");
+ callback.onError("UNKNOWN", "No crdentials available on this "
+ + "device");
} catch (RemoteException e) {
Log.i(
TAG,
diff --git a/services/credentials/java/com/android/server/credentials/GetRequestSession.java b/services/credentials/java/com/android/server/credentials/GetRequestSession.java
index 06396e0..f7c5905 100644
--- a/services/credentials/java/com/android/server/credentials/GetRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/GetRequestSession.java
@@ -19,6 +19,7 @@
import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Context;
+import android.credentials.GetCredentialException;
import android.credentials.GetCredentialRequest;
import android.credentials.GetCredentialResponse;
import android.credentials.IGetCredentialCallback;
@@ -40,10 +41,10 @@
implements ProviderSession.ProviderInternalCallback<GetCredentialResponse> {
private static final String TAG = "GetRequestSession";
- public GetRequestSession(Context context, int userId,
+ public GetRequestSession(Context context, int userId, int callingUid,
IGetCredentialCallback callback, GetCredentialRequest request,
CallingAppInfo callingAppInfo) {
- super(context, userId, request, callback, RequestInfo.TYPE_GET, callingAppInfo);
+ super(context, userId, callingUid, request, callback, RequestInfo.TYPE_GET, callingAppInfo);
}
/**
@@ -75,17 +76,11 @@
mRequestId, mClientRequest, mClientAppInfo.getPackageName()),
providerDataList));
} catch (RemoteException e) {
- Log.i(TAG, "Issue with invoking pending intent: " + e.getMessage());
- // TODO: Propagate failure
+ respondToClientWithErrorAndFinish(
+ GetCredentialException.TYPE_UNKNOWN, "Unable to instantiate selector");
}
}
- @Override // from provider session
- public void onProviderStatusChanged(ProviderSession.Status status,
- ComponentName componentName) {
- super.onProviderStatusChanged(status, componentName);
- }
-
@Override
public void onFinalResponseReceived(ComponentName componentName,
@Nullable GetCredentialResponse response) {
@@ -93,8 +88,7 @@
if (response != null) {
respondToClientWithResponseAndFinish(response);
} else {
- // TODO("Replace with no credentials/unknown type when ready)
- respondToClientWithErrorAndFinish("unknown_type",
+ respondToClientWithErrorAndFinish(GetCredentialException.TYPE_NO_CREDENTIAL,
"Invalid response from provider");
}
}
@@ -108,29 +102,48 @@
}
private void respondToClientWithResponseAndFinish(GetCredentialResponse response) {
- Log.i(TAG, "respondToClientWithResponseAndFinish");
try {
mClientCallback.onResponse(response);
+ logApiCalled(RequestType.GET_CREDENTIALS, /* isSuccessful */ true);
} catch (RemoteException e) {
- e.printStackTrace();
+ Log.i(TAG, "Issue while responding to client with a response : " + e.getMessage());
+ logApiCalled(RequestType.GET_CREDENTIALS, /* isSuccessful */ false);
}
finishSession();
}
private void respondToClientWithErrorAndFinish(String errorType, String errorMsg) {
- Log.i(TAG, "respondToClientWithErrorAndFinish");
try {
mClientCallback.onError(errorType, errorMsg);
} catch (RemoteException e) {
- e.printStackTrace();
+ Log.i(TAG, "Issue while responding to client with error : " + e.getMessage());
+
}
+ logApiCalled(RequestType.GET_CREDENTIALS, /* isSuccessful */ false);
finishSession();
}
@Override
public void onUiCancellation() {
- // TODO("Replace with properly defined error type")
- respondToClientWithErrorAndFinish("user_canceled",
+ respondToClientWithErrorAndFinish(GetCredentialException.TYPE_USER_CANCELED,
"User cancelled the selector");
}
+
+ @Override
+ public void onProviderStatusChanged(ProviderSession.Status status,
+ ComponentName componentName) {
+ Log.i(TAG, "in onStatusChanged with status: " + status);
+ if (!isAnyProviderPending()) {
+ // If all provider responses have been received, we can either need the UI,
+ // or we need to respond with error. The only other case is the entry being
+ // selected after the UI has been invoked which has a separate code path.
+ if (isUiInvocationNeeded()) {
+ Log.i(TAG, "in onProviderStatusChanged - isUiInvocationNeeded");
+ getProviderDataAndInitiateUi();
+ } else {
+ respondToClientWithErrorAndFinish(GetCredentialException.TYPE_NO_CREDENTIAL,
+ "No credentials available");
+ }
+ }
+ }
}
diff --git a/services/credentials/java/com/android/server/credentials/PendingIntentResultHandler.java b/services/credentials/java/com/android/server/credentials/PendingIntentResultHandler.java
index 8796314..c2b346f 100644
--- a/services/credentials/java/com/android/server/credentials/PendingIntentResultHandler.java
+++ b/services/credentials/java/com/android/server/credentials/PendingIntentResultHandler.java
@@ -39,6 +39,12 @@
return pendingIntentResponse.getResultCode() == Activity.RESULT_OK;
}
+ /** Returns true if the pending intent was cancelled by the user. */
+ public static boolean isCancelledResponse(
+ ProviderPendingIntentResponse pendingIntentResponse) {
+ return pendingIntentResponse.getResultCode() == Activity.RESULT_CANCELED;
+ }
+
/** Extracts the {@link CredentialsResponseContent} object added to the result data. */
public static CredentialsResponseContent extractResponseContent(Intent resultData) {
if (resultData == null) {
diff --git a/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java b/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java
index 9163b8e..7a24a22 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java
@@ -22,6 +22,7 @@
import android.content.Context;
import android.content.Intent;
import android.credentials.CreateCredentialException;
+import android.credentials.CreateCredentialResponse;
import android.credentials.ui.CreateCredentialProviderData;
import android.credentials.ui.Entry;
import android.credentials.ui.ProviderPendingIntentResponse;
@@ -98,7 +99,7 @@
private ProviderCreateSession(
@NonNull Context context,
@NonNull CredentialProviderInfo info,
- @NonNull ProviderInternalCallback callbacks,
+ @NonNull ProviderInternalCallback<CreateCredentialResponse> callbacks,
@UserIdInt int userId,
@NonNull RemoteCredentialService remoteCredentialService,
@NonNull BeginCreateCredentialRequest beginCreateRequest,
@@ -180,9 +181,7 @@
onSaveEntrySelected(providerPendingIntentResponse);
} else {
Log.i(TAG, "Unexpected save entry key");
- // TODO("Replace with no credentials error type");
- invokeCallbackWithError("unknown_type",
- "Issue while retrieving credential");
+ invokeCallbackOnInternalInvalidState();
}
break;
case REMOTE_ENTRY_KEY:
@@ -190,9 +189,7 @@
onRemoteEntrySelected(providerPendingIntentResponse);
} else {
Log.i(TAG, "Unexpected remote entry key");
- // TODO("Replace with unknown/no credentials exception")
- invokeCallbackWithError("unknown_type",
- "Issue while retrieving credential");
+ invokeCallbackOnInternalInvalidState();
}
break;
default:
@@ -248,23 +245,16 @@
} else {
Log.i(TAG, "onSaveEntrySelected - no response or error found in pending "
+ "intent response");
- invokeCallbackWithError(
- // TODO("Replace with unknown/no credentials exception")
- "unknown",
- "Issue encountered while retrieving the credential");
+ invokeCallbackOnInternalInvalidState();
}
}
- private void invokeCallbackWithError(String errorType, @Nullable String message) {
- mCallbacks.onFinalErrorReceived(mComponentName, errorType, message);
- }
-
@Nullable
private CreateCredentialException maybeGetPendingIntentException(
ProviderPendingIntentResponse pendingIntentResponse) {
if (pendingIntentResponse == null) {
Log.i(TAG, "pendingIntentResponse is null");
- return null;
+ return new CreateCredentialException(CreateCredentialException.TYPE_NO_CREDENTIAL);
}
if (PendingIntentResultHandler.isValidResponse(pendingIntentResponse)) {
CreateCredentialException exception = PendingIntentResultHandler
@@ -273,11 +263,21 @@
Log.i(TAG, "Pending intent contains provider exception");
return exception;
}
+ } else if (PendingIntentResultHandler.isCancelledResponse(pendingIntentResponse)) {
+ return new CreateCredentialException(CreateCredentialException.TYPE_USER_CANCELED);
} else {
- Log.i(TAG, "Pending intent result code not Activity.RESULT_OK");
- // TODO("Update with unknown exception when ready")
- return new CreateCredentialException("unknown");
+ return new CreateCredentialException(CreateCredentialException.TYPE_NO_CREDENTIAL);
}
return null;
}
+
+ /**
+ * When an invalid state occurs, e.g. entry mismatch or no response from provider,
+ * we send back a TYPE_UNKNOWN error as to the developer.
+ */
+ private void invokeCallbackOnInternalInvalidState() {
+ mCallbacks.onFinalErrorReceived(mComponentName,
+ CreateCredentialException.TYPE_UNKNOWN,
+ null);
+ }
}
diff --git a/services/credentials/java/com/android/server/credentials/ProviderGetSession.java b/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
index 9846d83..95f2313 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
@@ -144,7 +144,7 @@
public ProviderGetSession(Context context,
CredentialProviderInfo info,
- ProviderInternalCallback callbacks,
+ ProviderInternalCallback<GetCredentialResponse> callbacks,
int userId, RemoteCredentialService remoteCredentialService,
BeginGetCredentialRequest beginGetRequest,
android.credentials.GetCredentialRequest completeGetRequest) {
@@ -195,9 +195,7 @@
CredentialEntry credentialEntry = mUiCredentialEntries.get(entryKey);
if (credentialEntry == null) {
Log.i(TAG, "Unexpected credential entry key");
- // TODO("Replace with no credentials/unknown exception")
- invokeCallbackWithError("unknown_type",
- "Issue while retrieving credential");
+ invokeCallbackOnInternalInvalidState();
return;
}
onCredentialEntrySelected(credentialEntry, providerPendingIntentResponse);
@@ -206,9 +204,7 @@
Action actionEntry = mUiActionsEntries.get(entryKey);
if (actionEntry == null) {
Log.i(TAG, "Unexpected action entry key");
- // TODO("Replace with no credentials/unknown exception")
- invokeCallbackWithError("unknown_type",
- "Issue while retrieving credential");
+ invokeCallbackOnInternalInvalidState();
return;
}
onActionEntrySelected(providerPendingIntentResponse);
@@ -218,9 +214,7 @@
onAuthenticationEntrySelected(providerPendingIntentResponse);
} else {
Log.i(TAG, "Unexpected authentication entry key");
- // TODO("Replace with no credentials/unknown exception")
- invokeCallbackWithError("unknown_type",
- "Issue while retrieving credential");
+ invokeCallbackOnInternalInvalidState();
}
break;
case REMOTE_ENTRY_KEY:
@@ -228,9 +222,7 @@
onRemoteEntrySelected(providerPendingIntentResponse);
} else {
Log.i(TAG, "Unexpected remote entry key");
- // TODO("Replace with no credentials/unknown exception")
- invokeCallbackWithError("unknown_type",
- "Issue while retrieving credential");
+ invokeCallbackOnInternalInvalidState();
}
break;
default:
@@ -238,11 +230,6 @@
}
}
- private void invokeCallbackWithError(String errorType, @Nullable String errorMessage) {
- // TODO: Determine what the error message should be
- mCallbacks.onFinalErrorReceived(mComponentName, errorType, errorMessage);
- }
-
@Override // Call from request session to data to be shown on the UI
@Nullable protected GetCredentialProviderData prepareUiData() throws IllegalArgumentException {
Log.i(TAG, "In prepareUiData");
@@ -288,7 +275,8 @@
String entryId = generateEntryId();
Entry authEntry = new Entry(
AUTHENTICATION_ACTION_ENTRY_KEY, entryId,
- authenticationAction.getSlice());
+ authenticationAction.getSlice(),
+ setUpFillInIntentForAuthentication());
mUiAuthenticationAction = new Pair<>(entryId, authenticationAction);
return authEntry;
}
@@ -324,6 +312,15 @@
return intent;
}
+ private Intent setUpFillInIntentForAuthentication() {
+ Intent intent = new Intent();
+ intent.putExtra(
+ CredentialProviderService
+ .EXTRA_BEGIN_GET_CREDENTIAL_REQUEST,
+ mProviderRequest);
+ return intent;
+ }
+
private List<Entry> prepareUiActionEntries(@Nullable List<Action> actions) {
List<Entry> actionEntries = new ArrayList<>();
for (Action action : actions) {
@@ -369,20 +366,20 @@
}
Log.i(TAG, "Pending intent response contains no credential, or error");
- // TODO("Replace with no credentials/unknown error when ready)
- invokeCallbackWithError("unknown_type",
- "Issue while retrieving credential");
+ invokeCallbackOnInternalInvalidState();
}
Log.i(TAG, "CredentialEntry does not have a credential or a pending intent result");
- // TODO("Replace with no credentials/unknown error when ready)
- invokeCallbackWithError("unknown_type",
- "Error encountered while retrieving the credential");
+ invokeCallbackOnInternalInvalidState();
}
private void onAuthenticationEntrySelected(
@Nullable ProviderPendingIntentResponse providerPendingIntentResponse) {
//TODO: Other provider intent statuses
- // Check if pending intent has an error
+ if (providerPendingIntentResponse == null) {
+ Log.i(TAG, "providerPendingIntentResponse is null");
+ onUpdateEmptyResponse();
+ }
+
GetCredentialException exception = maybeGetPendingIntentException(
providerPendingIntentResponse);
if (exception != null) {
@@ -401,9 +398,7 @@
}
Log.i(TAG, "No error or respond found in pending intent response");
- // TODO("Replace with no credentials/unknown error when ready)
- invokeCallbackWithError("unknown type", "Issue"
- + " while retrieving credential");
+ onUpdateEmptyResponse();
}
private void onActionEntrySelected(ProviderPendingIntentResponse
@@ -425,6 +420,10 @@
}
}
+ private void onUpdateEmptyResponse() {
+ updateStatusAndInvokeCallback(Status.NO_CREDENTIALS);
+ }
+
@Nullable
private GetCredentialException maybeGetPendingIntentException(
ProviderPendingIntentResponse pendingIntentResponse) {
@@ -439,11 +438,20 @@
Log.i(TAG, "Pending intent contains provider exception");
return exception;
}
+ } else if (PendingIntentResultHandler.isCancelledResponse(pendingIntentResponse)) {
+ return new GetCredentialException(GetCredentialException.TYPE_USER_CANCELED);
} else {
- Log.i(TAG, "Pending intent result code not Activity.RESULT_OK");
- // TODO("Update with unknown exception when ready")
- return new GetCredentialException("unknown");
+ return new GetCredentialException(GetCredentialException.TYPE_NO_CREDENTIAL);
}
return null;
}
+
+ /**
+ * When an invalid state occurs, e.g. entry mismatch or no response from provider,
+ * we send back a TYPE_UNKNOWN error as to the developer.
+ */
+ private void invokeCallbackOnInternalInvalidState() {
+ mCallbacks.onFinalErrorReceived(mComponentName,
+ GetCredentialException.TYPE_UNKNOWN, null);
+ }
}
diff --git a/services/credentials/java/com/android/server/credentials/ProviderSession.java b/services/credentials/java/com/android/server/credentials/ProviderSession.java
index 93e816a..678c752 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderSession.java
@@ -133,7 +133,7 @@
PENDING_INTENT_INVOKED,
CREDENTIAL_RECEIVED_FROM_SELECTION,
SAVE_ENTRIES_RECEIVED, CANCELED,
- COMPLETE
+ NO_CREDENTIALS, COMPLETE
}
/** Converts exception to a provider session status. */
@@ -191,6 +191,11 @@
return mProviderResponse != null || mProviderResponseSet;
}
+ protected void invokeCallbackWithError(String errorType, @Nullable String errorMessage) {
+ // TODO: Determine what the error message should be
+ mCallbacks.onFinalErrorReceived(mComponentName, errorType, errorMessage);
+ }
+
/** Update the response state stored with the provider session. */
@Nullable protected R getProviderResponse() {
return mProviderResponse;
diff --git a/services/credentials/java/com/android/server/credentials/RequestSession.java b/services/credentials/java/com/android/server/credentials/RequestSession.java
index f59a0ef..8e44f0f 100644
--- a/services/credentials/java/com/android/server/credentials/RequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/RequestSession.java
@@ -16,9 +16,15 @@
package com.android.server.credentials;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CLEAR_CREDENTIAL;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CREATE_CREDENTIAL;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_GET_CREDENTIAL;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_UNKNOWN;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_FAILURE;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_SUCCESS;
+
import android.annotation.NonNull;
import android.annotation.UserIdInt;
-import android.content.ComponentName;
import android.content.Context;
import android.credentials.ui.ProviderData;
import android.credentials.ui.UserSelectionDialogResult;
@@ -30,6 +36,8 @@
import android.service.credentials.CredentialProviderInfo;
import android.util.Log;
+import com.android.internal.util.FrameworkStatsLog;
+
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
@@ -38,28 +46,53 @@
* Base class of a request session, that listens to UI events. This class must be extended
* every time a new response type is expected from the providers.
*/
-abstract class RequestSession<T, U> implements CredentialManagerUi.CredentialManagerUiCallback{
+abstract class RequestSession<T, U> implements CredentialManagerUi.CredentialManagerUiCallback {
private static final String TAG = "RequestSession";
+ // Metrics constants
+ private static final int METRICS_API_NAME_UNKNOWN =
+ CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_UNKNOWN;
+ private static final int METRICS_API_NAME_GET_CREDENTIAL =
+ CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_GET_CREDENTIAL;
+ private static final int METRICS_API_NAME_CREATE_CREDENTIAL =
+ CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CREATE_CREDENTIAL;
+ private static final int METRICS_API_NAME_CLEAR_CREDENTIAL =
+ CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CLEAR_CREDENTIAL;
+ private static final int METRICS_API_STATUS_SUCCESS =
+ CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_SUCCESS;
+ private static final int METRICS_API_STATUS_FAILURE =
+ CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_FAILURE;
+
// TODO: Revise access levels of attributes
- @NonNull protected final T mClientRequest;
- @NonNull protected final U mClientCallback;
- @NonNull protected final IBinder mRequestId;
- @NonNull protected final Context mContext;
- @NonNull protected final CredentialManagerUi mCredentialManagerUi;
- @NonNull protected final String mRequestType;
- @NonNull protected final Handler mHandler;
- @UserIdInt protected final int mUserId;
- @NonNull protected final CallingAppInfo mClientAppInfo;
+ @NonNull
+ protected final T mClientRequest;
+ @NonNull
+ protected final U mClientCallback;
+ @NonNull
+ protected final IBinder mRequestId;
+ @NonNull
+ protected final Context mContext;
+ @NonNull
+ protected final CredentialManagerUi mCredentialManagerUi;
+ @NonNull
+ protected final String mRequestType;
+ @NonNull
+ protected final Handler mHandler;
+ @UserIdInt
+ protected final int mUserId;
+ private final int mCallingUid;
+ @NonNull
+ protected final CallingAppInfo mClientAppInfo;
protected final Map<String, ProviderSession> mProviders = new HashMap<>();
protected RequestSession(@NonNull Context context,
- @UserIdInt int userId, @NonNull T clientRequest, U clientCallback,
+ @UserIdInt int userId, int callingUid, @NonNull T clientRequest, U clientCallback,
@NonNull String requestType,
CallingAppInfo callingAppInfo) {
mContext = context;
mUserId = userId;
+ mCallingUid = callingUid;
mClientRequest = clientRequest;
mClientCallback = clientCallback;
mRequestType = requestType;
@@ -98,41 +131,6 @@
finishSession();
}
- protected void onProviderStatusChanged(ProviderSession.Status status,
- ComponentName componentName) {
- Log.i(TAG, "in onStatusChanged with status: " + status);
- if (ProviderSession.isTerminatingStatus(status)) {
- Log.i(TAG, "in onStatusChanged terminating status");
- onProviderTerminated(componentName);
- //TODO: Check if this was the provider we were waiting for and can invoke the UI now
- } else if (ProviderSession.isCompletionStatus(status)) {
- Log.i(TAG, "in onStatusChanged isCompletionStatus status");
- onProviderResponseComplete(componentName);
- } else if (ProviderSession.isUiInvokingStatus(status)) {
- Log.i(TAG, "in onStatusChanged isUiInvokingStatus status");
- onProviderResponseRequiresUi();
- }
- }
-
- protected void onProviderTerminated(ComponentName componentName) {
- //TODO: Implement
- }
-
- protected void onProviderResponseComplete(ComponentName componentName) {
- //TODO: Implement
- }
-
- protected void onProviderResponseRequiresUi() {
- Log.i(TAG, "in onProviderResponseComplete");
- // TODO: Determine whether UI has already been invoked, and deal accordingly
- if (!isAnyProviderPending()) {
- Log.i(TAG, "in onProviderResponseComplete - isResponseCompleteAcrossProviders");
- getProviderDataAndInitiateUi();
- } else {
- Log.i(TAG, "Can't invoke UI - waiting on some providers");
- }
- }
-
protected void finishSession() {
Log.i(TAG, "finishing session");
clearProviderSessions();
@@ -144,7 +142,7 @@
mProviders.clear();
}
- boolean isAnyProviderPending() {
+ protected boolean isAnyProviderPending() {
for (ProviderSession session : mProviders.values()) {
if (ProviderSession.isStatusWaitingForRemoteResponse(session.getStatus())) {
return true;
@@ -153,7 +151,49 @@
return false;
}
- private void getProviderDataAndInitiateUi() {
+ // TODO: move these definitions to a separate logging focused class.
+ enum RequestType {
+ GET_CREDENTIALS,
+ CREATE_CREDENTIALS,
+ CLEAR_CREDENTIALS,
+ }
+
+ private static int getApiNameFromRequestType(RequestType requestType) {
+ switch (requestType) {
+ case GET_CREDENTIALS:
+ return METRICS_API_NAME_GET_CREDENTIAL;
+ case CREATE_CREDENTIALS:
+ return METRICS_API_NAME_CREATE_CREDENTIAL;
+ case CLEAR_CREDENTIALS:
+ return METRICS_API_NAME_CLEAR_CREDENTIAL;
+ default:
+ return METRICS_API_NAME_UNKNOWN;
+ }
+ }
+
+ protected void logApiCalled(RequestType requestType, boolean isSuccessful) {
+ FrameworkStatsLog.write(FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED,
+ /* api_name */getApiNameFromRequestType(requestType), /* caller_uid */
+ mCallingUid, /* api_status */
+ isSuccessful ? METRICS_API_STATUS_SUCCESS : METRICS_API_STATUS_FAILURE);
+ }
+
+ /**
+ * Returns true if at least one provider is ready for UI invocation, and no
+ * provider is pending a response.
+ */
+ boolean isUiInvocationNeeded() {
+ for (ProviderSession session : mProviders.values()) {
+ if (ProviderSession.isUiInvokingStatus(session.getStatus())) {
+ return true;
+ } else if (ProviderSession.isStatusWaitingForRemoteResponse(session.getStatus())) {
+ return false;
+ }
+ }
+ return false;
+ }
+
+ void getProviderDataAndInitiateUi() {
Log.i(TAG, "In getProviderDataAndInitiateUi");
Log.i(TAG, "In getProviderDataAndInitiateUi providers size: " + mProviders.size());
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 8be3df4..fa6fa53 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -146,6 +146,7 @@
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT;
import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE;
+import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE_BLOCKING;
import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK;
import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
import static android.provider.DeviceConfig.NAMESPACE_DEVICE_POLICY_MANAGER;
@@ -1091,13 +1092,13 @@
// (ACTION_DATE_CHANGED), or when manual clock adjustment is made
// (ACTION_TIME_CHANGED)
updateSystemUpdateFreezePeriodsRecord(/* saveIfChanged */ true);
- final int userId = getManagedUserId(UserHandle.USER_SYSTEM);
+ final int userId = getManagedUserId(mUserManager.getMainUser().getIdentifier());
if (userId >= 0) {
updatePersonalAppsSuspension(userId, mUserManager.isUserUnlocked(userId));
}
} else if (ACTION_PROFILE_OFF_DEADLINE.equals(action)) {
Slogf.i(LOG_TAG, "Profile off deadline alarm was triggered");
- final int userId = getManagedUserId(UserHandle.USER_SYSTEM);
+ final int userId = getManagedUserId(mUserManager.getMainUser().getIdentifier());
if (userId >= 0) {
updatePersonalAppsSuspension(userId, mUserManager.isUserUnlocked(userId));
} else {
@@ -8597,9 +8598,20 @@
Preconditions.checkArgument(admin != null);
final CallerIdentity caller = getCallerIdentity();
- // Cannot be called while holding the lock:
- final boolean hasIncompatibleAccountsOrNonAdb =
- hasIncompatibleAccountsOrNonAdbNoLock(caller, userId, admin);
+
+ boolean hasIncompatibleAccountsOrNonAdb =
+ !isAdb(caller) || hasIncompatibleAccountsOnAnyUser();
+
+ if (!hasIncompatibleAccountsOrNonAdb) {
+ synchronized (getLockObject()) {
+ if (!isAdminTestOnlyLocked(admin, userId) && hasAccountsOnAnyUser()) {
+ Slogf.w(LOG_TAG,
+ "Non test-only owner can't be installed with existing accounts.");
+ return false;
+ }
+ }
+ }
+
synchronized (getLockObject()) {
enforceCanSetDeviceOwnerLocked(caller, admin, userId, hasIncompatibleAccountsOrNonAdb);
Preconditions.checkArgument(isPackageInstalledForUser(admin.getPackageName(), userId),
@@ -14745,14 +14757,10 @@
if (isAdb) {
// If shell command runs after user setup completed check device status. Otherwise, OK.
if (mIsWatch || hasUserSetupCompleted(UserHandle.USER_SYSTEM)) {
- // In non-headless system user mode, DO can be setup only if
- // there's no non-system user.
- // In headless system user mode, DO can be setup only if there are
- // two users: the headless system user and the foreground user.
- // If there could be multiple foreground users, this constraint should be modified.
+ // DO can be setup only if there are no users which are neither created by default
+ // nor marked as FOR_TESTING
- int maxNumberOfExistingUsers = isHeadlessSystemUserMode ? 2 : 1;
- if (mUserManager.getUserCount() > maxNumberOfExistingUsers) {
+ if (nonTestNonPrecreatedUsersExist()) {
return STATUS_NONSYSTEM_USER_EXISTS;
}
@@ -14782,6 +14790,17 @@
}
}
+ /**
+ * True if there are any users on the device which were not setup by default (1 usually, 2 for
+ * devices with a headless system user) and also are not marked as FOR_TESTING.
+ */
+ private boolean nonTestNonPrecreatedUsersExist() {
+ int allowedUsers = UserManager.isHeadlessSystemUserMode() ? 2 : 1;
+ return mUserManagerInternal.getUsers(/* excludeDying= */ true).stream()
+ .filter(u -> !u.isForTesting())
+ .count() > allowedUsers;
+ }
+
private int checkDeviceOwnerProvisioningPreCondition(@UserIdInt int callingUserId) {
synchronized (getLockObject()) {
final int deviceOwnerUserId = mInjector.userManagerIsHeadlessSystemUserMode()
@@ -16053,8 +16072,10 @@
wtfIfInLock();
return mInjector.binderWithCleanCallingIdentity(() -> {
- final AccountManager am = AccountManager.get(mContext);
- final Account accounts[] = am.getAccountsAsUser(userId);
+ AccountManager am =
+ mContext.createContextAsUser(UserHandle.of(userId), /* flags= */ 0)
+ .getSystemService(AccountManager.class);
+ Account[] accounts = am.getAccounts();
if (accounts.length == 0) {
return false;
}
@@ -18168,8 +18189,10 @@
.addAction(turnProfileOnButton)
.addExtras(extras)
.build();
- mInjector.getNotificationManager().notify(
- SystemMessage.NOTE_PERSONAL_APPS_SUSPENDED, notification);
+
+ mInjector.getNotificationManager().notifyAsUser(
+ null, SystemMessage.NOTE_PERSONAL_APPS_SUSPENDED, notification,
+ UserHandle.of(getProfileParentId(profileUserId)));
}
private String getPersonalAppSuspensionButtonText() {
@@ -19125,6 +19148,9 @@
if (preferentialNetworkServiceConfig.isEnabled()) {
if (preferentialNetworkServiceConfig.isFallbackToDefaultConnectionAllowed()) {
preferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
+ } else if (preferentialNetworkServiceConfig.shouldBlockNonMatchingNetworks()) {
+ preferenceBuilder.setPreference(
+ PROFILE_NETWORK_PREFERENCE_ENTERPRISE_BLOCKING);
} else {
preferenceBuilder.setPreference(
PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
@@ -19533,6 +19559,14 @@
}
@Override
+ public void resetShouldAllowBypassingDevicePolicyManagementRoleQualificationState() {
+ Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(
+ android.Manifest.permission.MANAGE_ROLE_HOLDERS));
+ setBypassDevicePolicyManagementRoleQualificationStateInternal(
+ /* currentRoleHolder= */ null, /* allowBypass= */ false);
+ }
+
+ @Override
public boolean shouldAllowBypassingDevicePolicyManagementRoleQualification() {
Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(
android.Manifest.permission.MANAGE_ROLE_HOLDERS));
@@ -19546,15 +19580,51 @@
}
private boolean shouldAllowBypassingDevicePolicyManagementRoleQualificationInternal() {
- if (mUserManager.getUserCount() > 1) {
+ if (nonTestNonPrecreatedUsersExist()) {
return false;
}
- AccountManager am = AccountManager.get(mContext);
- Account[] accounts = am.getAccounts();
- if (accounts.length == 0) {
- return true;
+
+
+ return !hasIncompatibleAccountsOnAnyUser();
+ }
+
+ private boolean hasAccountsOnAnyUser() {
+ long callingIdentity = Binder.clearCallingIdentity();
+ try {
+ for (UserInfo user : mUserManagerInternal.getUsers(/* excludeDying= */ true)) {
+ AccountManager am = mContext.createContextAsUser(
+ UserHandle.of(user.id), /* flags= */ 0)
+ .getSystemService(AccountManager.class);
+ Account[] accounts = am.getAccounts();
+ if (accounts.length != 0) {
+ return true;
+ }
+ }
+
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(callingIdentity);
}
- return !hasIncompatibleAccounts(am, accounts);
+ }
+
+ private boolean hasIncompatibleAccountsOnAnyUser() {
+ long callingIdentity = Binder.clearCallingIdentity();
+ try {
+ for (UserInfo user : mUserManagerInternal.getUsers(/* excludeDying= */ true)) {
+ AccountManager am = mContext.createContextAsUser(
+ UserHandle.of(user.id), /* flags= */ 0)
+ .getSystemService(AccountManager.class);
+ Account[] accounts = am.getAccounts();
+
+ if (hasIncompatibleAccounts(am, accounts)) {
+ return true;
+ }
+ }
+
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(callingIdentity);
+ }
}
private void setBypassDevicePolicyManagementRoleQualificationStateInternal(
diff --git a/services/java/com/android/server/BootUserInitializer.java b/services/java/com/android/server/BootUserInitializer.java
index deebfc7..3d71739 100644
--- a/services/java/com/android/server/BootUserInitializer.java
+++ b/services/java/com/android/server/BootUserInitializer.java
@@ -17,7 +17,6 @@
import android.annotation.UserIdInt;
import android.content.ContentResolver;
-import android.content.pm.UserInfo;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
@@ -27,8 +26,6 @@
import com.android.server.utils.Slogf;
import com.android.server.utils.TimingsTraceAndSlog;
-import java.util.List;
-
/**
* Class responsible for booting the device in the proper user on headless system user mode.
*
@@ -56,50 +53,18 @@
// this class or the setup wizard app
provisionHeadlessSystemUser();
- UserManagerInternal um = LocalServices.getService(UserManagerInternal.class);
- t.traceBegin("get-existing-users");
- List<UserInfo> existingUsers = um.getUsers(/* excludeDying= */ true);
- t.traceEnd();
-
- Slogf.d(TAG, "%d existing users", existingUsers.size());
-
- int initialUserId = UserHandle.USER_NULL;
-
- for (int i = 0; i < existingUsers.size(); i++) {
- UserInfo user = existingUsers.get(i);
- if (DEBUG) {
- Slogf.d(TAG, "User at position %d: %s", i, user.toFullString());
- }
- if (user.id != UserHandle.USER_SYSTEM && user.isFull()) {
- if (DEBUG) {
- Slogf.d(TAG, "Found initial user: %d", user.id);
- }
- initialUserId = user.id;
- break;
- }
- }
-
- if (initialUserId == UserHandle.USER_NULL) {
- Slogf.d(TAG, "Creating initial user");
- t.traceBegin("create-initial-user");
- try {
- int flags = UserInfo.FLAG_ADMIN | UserInfo.FLAG_MAIN;
- // TODO(b/204091126): proper name for user
- UserInfo newUser = um.createUserEvenWhenDisallowed("Real User",
- UserManager.USER_TYPE_FULL_SECONDARY, flags,
- /* disallowedPackages= */ null, /* token= */ null);
- Slogf.i(TAG, "Created initial user: %s", newUser.toFullString());
- initialUserId = newUser.id;
- } catch (Exception e) {
- Slogf.wtf(TAG, "failed to created initial user", e);
- return;
- } finally {
- t.traceEnd(); // create-initial-user
- }
- }
-
unlockSystemUser(t);
- switchToInitialUser(initialUserId);
+
+ try {
+ t.traceBegin("getBootUser");
+ int bootUser = LocalServices.getService(UserManagerInternal.class).getBootUser();
+ t.traceEnd();
+ t.traceBegin("switchToBootUser-" + bootUser);
+ switchToBootUser(bootUser);
+ t.traceEnd();
+ } catch (UserManager.CheckedUserOperationException e) {
+ Slogf.wtf(TAG, "Failed to created boot user", e);
+ }
}
/* TODO(b/261791491): STOPSHIP - SUW should be responsible for this. */
@@ -152,12 +117,12 @@
}
}
- private void switchToInitialUser(@UserIdInt int initialUserId) {
- Slogf.i(TAG, "Switching to initial user %d", initialUserId);
- boolean started = mAms.startUserInForegroundWithListener(initialUserId,
+ private void switchToBootUser(@UserIdInt int bootUserId) {
+ Slogf.i(TAG, "Switching to boot user %d", bootUserId);
+ boolean started = mAms.startUserInForegroundWithListener(bootUserId,
/* unlockListener= */ null);
if (!started) {
- Slogf.wtf(TAG, "Failed to start user %d in foreground", initialUserId);
+ Slogf.wtf(TAG, "Failed to start user %d in foreground", bootUserId);
}
}
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 5ebf6ce..5c5442d 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -108,7 +108,6 @@
import com.android.server.am.ActivityManagerService;
import com.android.server.ambientcontext.AmbientContextManagerService;
import com.android.server.appbinding.AppBindingService;
-import com.android.server.art.ArtManagerLocal;
import com.android.server.art.ArtModuleServiceInitializer;
import com.android.server.art.DexUseManagerLocal;
import com.android.server.attention.AttentionManagerService;
@@ -132,8 +131,8 @@
import com.android.server.display.color.ColorDisplayService;
import com.android.server.dreams.DreamManagerService;
import com.android.server.emergency.EmergencyAffordanceService;
-import com.android.server.grammaticalinflection.GrammaticalInflectionService;
import com.android.server.gpu.GpuService;
+import com.android.server.grammaticalinflection.GrammaticalInflectionService;
import com.android.server.graphics.fonts.FontManagerService;
import com.android.server.hdmi.HdmiControlService;
import com.android.server.incident.IncidentCompanionService;
@@ -147,6 +146,7 @@
import com.android.server.media.MediaRouterService;
import com.android.server.media.metrics.MediaMetricsManagerService;
import com.android.server.media.projection.MediaProjectionManagerService;
+import com.android.server.net.NetworkManagementService;
import com.android.server.net.NetworkPolicyManagerService;
import com.android.server.net.watchlist.NetworkWatchlistService;
import com.android.server.notification.NotificationManagerService;
@@ -163,6 +163,7 @@
import com.android.server.pm.BackgroundInstallControlService;
import com.android.server.pm.CrossProfileAppsService;
import com.android.server.pm.DataLoaderManagerService;
+import com.android.server.pm.DexOptHelper;
import com.android.server.pm.DynamicCodeLoggingService;
import com.android.server.pm.Installer;
import com.android.server.pm.LauncherAppsService;
@@ -2770,7 +2771,7 @@
t.traceEnd();
t.traceBegin("ArtManagerLocal");
- LocalManagerRegistry.addManager(ArtManagerLocal.class, new ArtManagerLocal(context));
+ DexOptHelper.initializeArtManagerLocal(context, mPackageManagerService);
t.traceEnd();
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_UWB)) {
diff --git a/services/people/java/com/android/server/people/data/ContactsQueryHelper.java b/services/people/java/com/android/server/people/data/ContactsQueryHelper.java
index 8a3a44ae..0993295 100644
--- a/services/people/java/com/android/server/people/data/ContactsQueryHelper.java
+++ b/services/people/java/com/android/server/people/data/ContactsQueryHelper.java
@@ -21,6 +21,7 @@
import android.annotation.WorkerThread;
import android.content.Context;
import android.database.Cursor;
+import android.database.sqlite.SQLiteException;
import android.net.Uri;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
@@ -149,6 +150,8 @@
found = true;
}
+ } catch (SQLiteException exception) {
+ Slog.w("SQLite exception when querying contacts.", exception);
}
if (found && lookupKey != null && hasPhoneNumber) {
return queryPhoneNumber(lookupKey);
diff --git a/services/permission/java/com/android/server/permission/access/AccessCheckingService.kt b/services/permission/java/com/android/server/permission/access/AccessCheckingService.kt
index f549797..e416718 100644
--- a/services/permission/java/com/android/server/permission/access/AccessCheckingService.kt
+++ b/services/permission/java/com/android/server/permission/access/AccessCheckingService.kt
@@ -211,6 +211,12 @@
}
}
+ internal fun onSystemReady() {
+ mutateState {
+ with(policy) { onSystemReady() }
+ }
+ }
+
private val PackageManagerLocal.allPackageStates:
Pair<Map<String, PackageState>, Map<String, PackageState>>
get() = withUnfilteredSnapshot().use { it.packageStates to it.disabledSystemPackageStates }
diff --git a/services/permission/java/com/android/server/permission/access/AccessPolicy.kt b/services/permission/java/com/android/server/permission/access/AccessPolicy.kt
index e0f94c7..07a5e72 100644
--- a/services/permission/java/com/android/server/permission/access/AccessPolicy.kt
+++ b/services/permission/java/com/android/server/permission/access/AccessPolicy.kt
@@ -255,6 +255,13 @@
}
}
+ fun MutateStateScope.onSystemReady() {
+ newState.systemState.isSystemReady = true
+ forEachSchemePolicy {
+ with(it) { onSystemReady() }
+ }
+ }
+
fun BinaryXmlPullParser.parseSystemState(state: AccessState) {
forEachTag {
when (tagName) {
@@ -362,6 +369,8 @@
open fun MutateStateScope.onPackageUninstalled(packageName: String, appId: Int, userId: Int) {}
+ open fun MutateStateScope.onSystemReady() {}
+
open fun BinaryXmlPullParser.parseSystemState(state: AccessState) {}
open fun BinaryXmlSerializer.serializeSystemState(state: AccessState) {}
diff --git a/services/permission/java/com/android/server/permission/access/AccessState.kt b/services/permission/java/com/android/server/permission/access/AccessState.kt
index 9616193..5532311 100644
--- a/services/permission/java/com/android/server/permission/access/AccessState.kt
+++ b/services/permission/java/com/android/server/permission/access/AccessState.kt
@@ -50,6 +50,8 @@
var privilegedPermissionAllowlistPackages: IndexedListSet<String>,
var permissionAllowlist: PermissionAllowlist,
var implicitToSourcePermissions: IndexedMap<String, IndexedListSet<String>>,
+ var isSystemReady: Boolean,
+ // TODO: Get and watch the state for deviceAndProfileOwners
// Mapping from user ID to package name.
var deviceAndProfileOwners: IntMap<String>,
val permissionGroups: IndexedMap<String, PermissionGroupInfo>,
@@ -67,6 +69,7 @@
IndexedListSet(),
PermissionAllowlist(),
IndexedMap(),
+ false,
IntMap(),
IndexedMap(),
IndexedMap(),
@@ -85,6 +88,7 @@
privilegedPermissionAllowlistPackages,
permissionAllowlist,
implicitToSourcePermissions,
+ isSystemReady,
deviceAndProfileOwners,
permissionGroups.copy { it },
permissionTrees.copy { it },
diff --git a/services/permission/java/com/android/server/permission/access/collection/IndexedMap.kt b/services/permission/java/com/android/server/permission/access/collection/IndexedMap.kt
index f4e362c..998d206 100644
--- a/services/permission/java/com/android/server/permission/access/collection/IndexedMap.kt
+++ b/services/permission/java/com/android/server/permission/access/collection/IndexedMap.kt
@@ -148,6 +148,13 @@
return isChanged
}
+inline fun <K, V, R> IndexedMap<K, V>.mapIndexed(transform: (Int, K, V) -> R): IndexedList<R> =
+ IndexedList<R>().also { destination ->
+ forEachIndexed { index, key, value ->
+ transform(index, key, value).let { destination += it }
+ }
+ }
+
inline fun <K, V, R> IndexedMap<K, V>.mapNotNullIndexed(
transform: (Int, K, V) -> R?
): IndexedList<R> =
diff --git a/services/permission/java/com/android/server/permission/access/permission/Permission.kt b/services/permission/java/com/android/server/permission/access/permission/Permission.kt
index 7bfca12..714480c 100644
--- a/services/permission/java/com/android/server/permission/access/permission/Permission.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/Permission.kt
@@ -91,6 +91,9 @@
inline val isKnownSigner: Boolean
get() = protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_KNOWN_SIGNER)
+ inline val isModule: Boolean
+ get() = protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_MODULE)
+
inline val isOem: Boolean
get() = protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_OEM)
diff --git a/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt b/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
index acd0a3c..c7e9371 100644
--- a/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
@@ -73,6 +73,7 @@
import com.android.server.pm.UserManagerService
import com.android.server.pm.parsing.pkg.AndroidPackageUtils
import com.android.server.pm.permission.LegacyPermission
+import com.android.server.pm.permission.Permission as LegacyPermission2
import com.android.server.pm.permission.LegacyPermissionSettings
import com.android.server.pm.permission.LegacyPermissionState
import com.android.server.pm.permission.PermissionManagerServiceInterface
@@ -1673,43 +1674,80 @@
context.getSystemService(PermissionControllerManager::class.java)!!.dump(fd, args)
}
- override fun getPermissionTEMP(
- permissionName: String
- ): com.android.server.pm.permission.Permission? {
- // TODO("Not yet implemented")
- return null
+ override fun getPermissionTEMP(permissionName: String): LegacyPermission2? {
+ val permission = service.getState {
+ with(policy) { getPermissions()[permissionName] }
+ } ?: return null
+
+ return LegacyPermission2(
+ permission.permissionInfo, permission.type, permission.isReconciled, permission.appId,
+ permission.gids, permission.areGidsPerUser
+ )
}
- override fun getLegacyPermissions(): List<LegacyPermission> {
- // TODO("Not yet implemented")
- return emptyList()
- }
+ override fun getLegacyPermissions(): List<LegacyPermission> =
+ service.getState {
+ with(policy) { getPermissions() }
+ }.mapIndexed { _, _, permission ->
+ LegacyPermission(
+ permission.permissionInfo, permission.type, permission.appId, permission.gids
+ )
+ }
override fun readLegacyPermissionsTEMP(legacyPermissionSettings: LegacyPermissionSettings) {
// Package settings has been read when this method is called.
service.initialize()
- // TODO("Not yet implemented")
}
override fun writeLegacyPermissionsTEMP(legacyPermissionSettings: LegacyPermissionSettings) {
- // TODO("Not yet implemented")
+ service.getState {
+ val permissions = with(policy) { getPermissions() }
+ legacyPermissionSettings.replacePermissions(toLegacyPermissions(permissions))
+ val permissionTrees = with(policy) { getPermissionTrees() }
+ legacyPermissionSettings.replacePermissionTrees(toLegacyPermissions(permissionTrees))
+ }
}
+ private fun toLegacyPermissions(
+ permissions: IndexedMap<String, Permission>
+ ): List<LegacyPermission> =
+ permissions.mapIndexed { _, _, permission ->
+ // We don't need to provide UID and GIDs, which are only retrieved when dumping.
+ LegacyPermission(
+ permission.permissionInfo, permission.type, 0, EmptyArray.INT
+ )
+ }
+
override fun getLegacyPermissionState(appId: Int): LegacyPermissionState {
- // TODO("Not yet implemented")
- return LegacyPermissionState()
+ val legacyState = LegacyPermissionState()
+ val userIds = userManagerService.userIdsIncludingPreCreated
+ service.getState {
+ val permissions = with(policy) { getPermissions() }
+ userIds.forEachIndexed { _, userId ->
+ val permissionFlags = with(policy) { getUidPermissionFlags(appId, userId) }
+ ?: return@forEachIndexed
+
+ permissionFlags.forEachIndexed permissionFlags@{ _, permissionName, flags ->
+ val permission = permissions[permissionName] ?: return@permissionFlags
+ val legacyPermissionState = LegacyPermissionState.PermissionState(
+ permissionName,
+ permission.isRuntime,
+ PermissionFlags.isPermissionGranted(flags),
+ PermissionFlags.toApiFlags(flags)
+ )
+ legacyState.putPermissionState(legacyPermissionState, userId)
+ }
+ }
+ }
+ return legacyState
}
- override fun readLegacyPermissionStateTEMP() {
- // TODO("Not yet implemented")
- }
+ override fun readLegacyPermissionStateTEMP() {}
- override fun writeLegacyPermissionStateTEMP() {
- // TODO("Not yet implemented")
- }
+ override fun writeLegacyPermissionStateTEMP() {}
override fun onSystemReady() {
- // TODO STOPSHIP privappPermissionsViolationsfix check
+ service.onSystemReady()
permissionControllerManager = PermissionControllerManager(
context, PermissionThread.getHandler()
)
diff --git a/services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt b/services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt
index d0833bd..694efbb 100644
--- a/services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt
@@ -54,6 +54,8 @@
IndexedListSet<OnPermissionFlagsChangedListener>()
private val onPermissionFlagsChangedListenersLock = Any()
+ private val privilegedPermissionAllowlistViolations = IndexedSet<String>()
+
override val subjectScheme: String
get() = UidUri.SCHEME
@@ -734,7 +736,7 @@
} else {
newFlags = newFlags andInv PermissionFlags.LEGACY_GRANTED
val wasGrantedByImplicit = newFlags.hasBits(PermissionFlags.IMPLICIT_GRANTED)
- val isLeanBackNotificationsPermission = newState.systemState.isLeanback &&
+ val isLeanbackNotificationsPermission = newState.systemState.isLeanback &&
permissionName in NOTIFICATIONS_PERMISSIONS
val isImplicitPermission = anyPackageInAppId(appId) {
permissionName in it.androidPackage!!.implicitPermissions
@@ -748,7 +750,7 @@
}
!sourcePermission.isRuntime
} ?: false
- val shouldGrantByImplicit = isLeanBackNotificationsPermission ||
+ val shouldGrantByImplicit = isLeanbackNotificationsPermission ||
(isImplicitPermission && isAnySourcePermissionNonRuntime)
if (shouldGrantByImplicit) {
newFlags = newFlags or PermissionFlags.IMPLICIT_GRANTED
@@ -917,7 +919,21 @@
if (packageState.isUpdatedSystemApp) {
return true
}
- // TODO: Enforce the allowlist on boot
+ // Only enforce the privileged permission allowlist on boot
+ if (!newState.systemState.isSystemReady) {
+ // Apps that are in updated apex's do not need to be allowlisted
+ if (!packageState.isApkInUpdatedApex) {
+ Log.w(
+ LOG_TAG, "Privileged permission ${permission.name} for package" +
+ " ${packageState.packageName} (${packageState.path}) not in" +
+ " privileged permission allowlist"
+ )
+ if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) {
+ privilegedPermissionAllowlistViolations += "${packageState.packageName}" +
+ " (${packageState.path}): ${permission.name}"
+ }
+ }
+ }
return !RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE
}
@@ -1106,6 +1122,12 @@
// Special permission for the recents app.
return true
}
+ // TODO(b/261913353): STOPSHIP: Add AndroidPackage.apexModuleName.
+ // This should be androidPackage.apexModuleName instead
+ if (permission.isModule && androidPackage.packageName != null) {
+ // Special permission granted for APKs inside APEX modules.
+ return true
+ }
return false
}
@@ -1155,6 +1177,13 @@
return uid == ownerUid
}
+ override fun MutateStateScope.onSystemReady() {
+ if (!privilegedPermissionAllowlistViolations.isEmpty()) {
+ throw IllegalStateException("Signature|privileged permissions not in privileged" +
+ " permission allowlist: $privilegedPermissionAllowlistViolations")
+ }
+ }
+
override fun BinaryXmlPullParser.parseSystemState(state: AccessState) {
with(persistence) { this@parseSystemState.parseSystemState(state) }
}
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java
new file mode 100644
index 0000000..73d04c6
--- /dev/null
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.inputmethod;
+
+import static android.inputmethodservice.InputMethodService.IME_ACTIVE;
+
+import static com.android.internal.inputmethod.SoftInputShowHideReason.HIDE_SOFT_INPUT;
+import static com.android.internal.inputmethod.SoftInputShowHideReason.SHOW_SOFT_INPUT;
+import static com.android.server.inputmethod.ImeVisibilityStateComputer.STATE_HIDE_IME;
+import static com.android.server.inputmethod.ImeVisibilityStateComputer.STATE_HIDE_IME_EXPLICIT;
+import static com.android.server.inputmethod.ImeVisibilityStateComputer.STATE_HIDE_IME_NOT_ALWAYS;
+import static com.android.server.inputmethod.ImeVisibilityStateComputer.STATE_INVALID;
+import static com.android.server.inputmethod.ImeVisibilityStateComputer.STATE_SHOW_IME;
+import static com.android.server.inputmethod.ImeVisibilityStateComputer.STATE_SHOW_IME_IMPLICIT;
+
+import static org.junit.Assert.assertThrows;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import android.os.RemoteException;
+import android.view.inputmethod.InputMethodManager;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test the behavior of {@link DefaultImeVisibilityApplier} when performing or applying the IME
+ * visibility state.
+ *
+ * Build/Install/Run:
+ * atest FrameworksInputMethodSystemServerTests:DefaultImeVisibilityApplierTest
+ */
+@RunWith(AndroidJUnit4.class)
+public class DefaultImeVisibilityApplierTest extends InputMethodManagerServiceTestBase {
+ private DefaultImeVisibilityApplier mVisibilityApplier;
+
+ @Before
+ public void setUp() throws RemoteException {
+ super.setUp();
+ mVisibilityApplier =
+ (DefaultImeVisibilityApplier) mInputMethodManagerService.getVisibilityApplier();
+ mInputMethodManagerService.mCurFocusedWindowClient = mock(
+ InputMethodManagerService.ClientState.class);
+ }
+
+ @Test
+ public void testPerformShowIme() throws Exception {
+ mVisibilityApplier.performShowIme(mWindowToken, null, null, SHOW_SOFT_INPUT);
+ verifyShowSoftInput(false, true, InputMethodManager.SHOW_IMPLICIT);
+ }
+
+ @Test
+ public void testPerformHideIme() throws Exception {
+ mVisibilityApplier.performHideIme(mWindowToken, null, null, HIDE_SOFT_INPUT);
+ verifyHideSoftInput(false, true);
+ }
+
+ @Test
+ public void testApplyImeVisibility_throwForInvalidState() {
+ mVisibilityApplier.applyImeVisibility(mWindowToken, null, STATE_INVALID);
+ assertThrows(IllegalArgumentException.class,
+ () -> mVisibilityApplier.applyImeVisibility(mWindowToken, null, STATE_INVALID));
+ }
+
+ @Test
+ public void testApplyImeVisibility_showIme() {
+ mVisibilityApplier.applyImeVisibility(mWindowToken, null, STATE_SHOW_IME);
+ verify(mMockWindowManagerInternal).showImePostLayout(eq(mWindowToken), any());
+ }
+
+ @Test
+ public void testApplyImeVisibility_hideIme() {
+ mVisibilityApplier.applyImeVisibility(mWindowToken, null, STATE_HIDE_IME);
+ verify(mMockWindowManagerInternal).hideIme(eq(mWindowToken), anyInt(), any());
+ }
+
+ @Test
+ public void testApplyImeVisibility_hideImeExplicit() throws Exception {
+ mInputMethodManagerService.mImeWindowVis = IME_ACTIVE;
+ mVisibilityApplier.applyImeVisibility(mWindowToken, null, STATE_HIDE_IME_EXPLICIT);
+ verifyHideSoftInput(true, true);
+ }
+
+ @Test
+ public void testApplyImeVisibility_hideNotAlways() throws Exception {
+ mInputMethodManagerService.mImeWindowVis = IME_ACTIVE;
+ mVisibilityApplier.applyImeVisibility(mWindowToken, null, STATE_HIDE_IME_NOT_ALWAYS);
+ verifyHideSoftInput(true, true);
+ }
+
+ @Test
+ public void testApplyImeVisibility_showImeImplicit() throws Exception {
+ mVisibilityApplier.applyImeVisibility(mWindowToken, null, STATE_SHOW_IME_IMPLICIT);
+ verifyShowSoftInput(true, true, InputMethodManager.SHOW_IMPLICIT);
+ }
+}
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ImeVisibilityStateComputerTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ImeVisibilityStateComputerTest.java
new file mode 100644
index 0000000..8415fe1
--- /dev/null
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ImeVisibilityStateComputerTest.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.inputmethod;
+
+import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HIDDEN;
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.Display.INVALID_DISPLAY;
+import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY;
+import static android.view.WindowManager.DISPLAY_IME_POLICY_HIDE;
+import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED;
+
+import static com.android.server.inputmethod.ImeVisibilityStateComputer.ImeTargetWindowState;
+import static com.android.server.inputmethod.InputMethodManagerService.FALLBACK_DISPLAY_ID;
+import static com.android.server.inputmethod.InputMethodManagerService.ImeDisplayValidator;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.view.inputmethod.InputMethodManager;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.server.wm.WindowManagerInternal;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test the behavior of {@link ImeVisibilityStateComputer} and {@link ImeVisibilityApplier} when
+ * requesting the IME visibility.
+ *
+ * Build/Install/Run:
+ * atest FrameworksInputMethodSystemServerTests:ImeVisibilityStateComputerTest
+ */
+@RunWith(AndroidJUnit4.class)
+public class ImeVisibilityStateComputerTest extends InputMethodManagerServiceTestBase {
+ private ImeVisibilityStateComputer mComputer;
+ private int mImeDisplayPolicy = DISPLAY_IME_POLICY_LOCAL;
+
+ @Before
+ public void setUp() throws RemoteException {
+ super.setUp();
+ ImeVisibilityStateComputer.Injector injector = new ImeVisibilityStateComputer.Injector() {
+ @Override
+ public WindowManagerInternal getWmService() {
+ return mMockWindowManagerInternal;
+ }
+
+ @Override
+ public ImeDisplayValidator getImeValidator() {
+ return displayId -> mImeDisplayPolicy;
+ }
+ };
+ mComputer = new ImeVisibilityStateComputer(mInputMethodManagerService, injector);
+ }
+
+ @Test
+ public void testRequestImeVisibility_showImplicit() {
+ initImeTargetWindowState(mWindowToken);
+ boolean res = mComputer.onImeShowFlags(null, InputMethodManager.SHOW_IMPLICIT);
+ mComputer.requestImeVisibility(mWindowToken, res);
+
+ final ImeTargetWindowState state = mComputer.getWindowStateOrNull(mWindowToken);
+ assertThat(state).isNotNull();
+ assertThat(state.hasEdiorFocused()).isTrue();
+ assertThat(state.getSoftInputModeState()).isEqualTo(SOFT_INPUT_STATE_UNCHANGED);
+ assertThat(state.isRequestedImeVisible()).isTrue();
+
+ assertThat(mComputer.mRequestedShowExplicitly).isFalse();
+ }
+
+ @Test
+ public void testRequestImeVisibility_showExplicit() {
+ initImeTargetWindowState(mWindowToken);
+ boolean res = mComputer.onImeShowFlags(null, 0 /* show explicit */);
+ mComputer.requestImeVisibility(mWindowToken, res);
+
+ final ImeTargetWindowState state = mComputer.getWindowStateOrNull(mWindowToken);
+ assertThat(state).isNotNull();
+ assertThat(state.hasEdiorFocused()).isTrue();
+ assertThat(state.getSoftInputModeState()).isEqualTo(SOFT_INPUT_STATE_UNCHANGED);
+ assertThat(state.isRequestedImeVisible()).isTrue();
+
+ assertThat(mComputer.mRequestedShowExplicitly).isTrue();
+ }
+
+ @Test
+ public void testRequestImeVisibility_showImplicit_a11yNoImePolicy() {
+ // Precondition: set AccessibilityService#SHOW_MODE_HIDDEN policy
+ mComputer.getImePolicy().setA11yRequestNoSoftKeyboard(SHOW_MODE_HIDDEN);
+
+ initImeTargetWindowState(mWindowToken);
+ boolean res = mComputer.onImeShowFlags(null, InputMethodManager.SHOW_IMPLICIT);
+ mComputer.requestImeVisibility(mWindowToken, res);
+
+ final ImeTargetWindowState state = mComputer.getWindowStateOrNull(mWindowToken);
+ assertThat(state).isNotNull();
+ assertThat(state.hasEdiorFocused()).isTrue();
+ assertThat(state.getSoftInputModeState()).isEqualTo(SOFT_INPUT_STATE_UNCHANGED);
+ assertThat(state.isRequestedImeVisible()).isFalse();
+
+ assertThat(mComputer.mRequestedShowExplicitly).isFalse();
+ }
+
+ @Test
+ public void testRequestImeVisibility_showImplicit_imeHiddenPolicy() {
+ // Precondition: set IME hidden display policy before calling showSoftInput
+ mComputer.getImePolicy().setImeHiddenByDisplayPolicy(true);
+
+ initImeTargetWindowState(mWindowToken);
+ boolean res = mComputer.onImeShowFlags(null, InputMethodManager.SHOW_IMPLICIT);
+ mComputer.requestImeVisibility(mWindowToken, res);
+
+ final ImeTargetWindowState state = mComputer.getWindowStateOrNull(mWindowToken);
+ assertThat(state).isNotNull();
+ assertThat(state.hasEdiorFocused()).isTrue();
+ assertThat(state.getSoftInputModeState()).isEqualTo(SOFT_INPUT_STATE_UNCHANGED);
+ assertThat(state.isRequestedImeVisible()).isFalse();
+
+ assertThat(mComputer.mRequestedShowExplicitly).isFalse();
+ }
+
+ @Test
+ public void testRequestImeVisibility_hideNotAlways() {
+ // Precondition: ensure IME has shown before hiding request.
+ mComputer.setInputShown(true);
+
+ initImeTargetWindowState(mWindowToken);
+ assertThat(mComputer.canHideIme(null, InputMethodManager.HIDE_NOT_ALWAYS)).isTrue();
+ mComputer.requestImeVisibility(mWindowToken, false);
+
+ final ImeTargetWindowState state = mComputer.getWindowStateOrNull(mWindowToken);
+ assertThat(state).isNotNull();
+ assertThat(state.hasEdiorFocused()).isTrue();
+ assertThat(state.getSoftInputModeState()).isEqualTo(SOFT_INPUT_STATE_UNCHANGED);
+ assertThat(state.isRequestedImeVisible()).isFalse();
+ }
+
+ @Test
+ public void testComputeImeDisplayId() {
+ final ImeTargetWindowState state = mComputer.getOrCreateWindowState(mWindowToken);
+
+ mImeDisplayPolicy = DISPLAY_IME_POLICY_LOCAL;
+ mComputer.computeImeDisplayId(state, DEFAULT_DISPLAY);
+ assertThat(mComputer.getImePolicy().isImeHiddenByDisplayPolicy()).isFalse();
+ assertThat(state.getImeDisplayId()).isEqualTo(DEFAULT_DISPLAY);
+
+ mComputer.computeImeDisplayId(state, 10 /* displayId */);
+ assertThat(mComputer.getImePolicy().isImeHiddenByDisplayPolicy()).isFalse();
+ assertThat(state.getImeDisplayId()).isEqualTo(10);
+
+ mImeDisplayPolicy = DISPLAY_IME_POLICY_HIDE;
+ mComputer.computeImeDisplayId(state, 10 /* displayId */);
+ assertThat(mComputer.getImePolicy().isImeHiddenByDisplayPolicy()).isTrue();
+ assertThat(state.getImeDisplayId()).isEqualTo(INVALID_DISPLAY);
+
+ mImeDisplayPolicy = DISPLAY_IME_POLICY_FALLBACK_DISPLAY;
+ mComputer.computeImeDisplayId(state, 10 /* displayId */);
+ assertThat(mComputer.getImePolicy().isImeHiddenByDisplayPolicy()).isFalse();
+ assertThat(state.getImeDisplayId()).isEqualTo(FALLBACK_DISPLAY_ID);
+ }
+
+ private void initImeTargetWindowState(IBinder windowToken) {
+ final ImeTargetWindowState state = new ImeTargetWindowState(SOFT_INPUT_STATE_UNCHANGED,
+ 0, true, true, true);
+ mComputer.setWindowState(windowToken, state);
+ }
+}
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
index 640bde3..804bb49 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
@@ -26,6 +26,7 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -200,9 +201,8 @@
"TestServiceThread",
Process.THREAD_PRIORITY_FOREGROUND, /* allowIo */
false);
- mInputMethodManagerService =
- new InputMethodManagerService(
- mContext, mServiceThread, mMockInputMethodBindingController);
+ mInputMethodManagerService = new InputMethodManagerService(mContext, mServiceThread,
+ mMockInputMethodBindingController);
// Start a InputMethodManagerService.Lifecycle to publish and manage the lifecycle of
// InputMethodManagerService, which is closer to the real situation.
@@ -239,12 +239,17 @@
protected void verifyShowSoftInput(boolean setVisible, boolean showSoftInput)
throws RemoteException {
+ verifyShowSoftInput(setVisible, showSoftInput, anyInt());
+ }
+
+ protected void verifyShowSoftInput(boolean setVisible, boolean showSoftInput, int showFlags)
+ throws RemoteException {
synchronized (ImfLock.class) {
verify(mMockInputMethodBindingController, times(setVisible ? 1 : 0))
.setCurrentMethodVisible();
}
verify(mMockInputMethod, times(showSoftInput ? 1 : 0))
- .showSoftInput(any(), any(), anyInt(), any());
+ .showSoftInput(any(), any(), eq(showFlags), any());
}
protected void verifyHideSoftInput(boolean setNotVisible, boolean hideSoftInput)
diff --git a/services/tests/PackageManagerServiceTests/host/Android.bp b/services/tests/PackageManagerServiceTests/host/Android.bp
index 83677c2..47e7a37 100644
--- a/services/tests/PackageManagerServiceTests/host/Android.bp
+++ b/services/tests/PackageManagerServiceTests/host/Android.bp
@@ -30,11 +30,16 @@
"truth-prebuilt",
],
static_libs: [
+ "ApexInstallHelper",
"cts-host-utils",
"frameworks-base-hostutils",
"PackageManagerServiceHostTestsIntentVerifyUtils",
],
test_suites: ["general-tests"],
+ data: [
+ ":PackageManagerTestApex",
+ ":PackageManagerTestApexApp",
+ ],
java_resources: [
":PackageManagerTestOverlayActor",
":PackageManagerTestOverlay",
diff --git a/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/ApexUpdateTest.kt b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/ApexUpdateTest.kt
new file mode 100644
index 0000000..44b4e30
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/ApexUpdateTest.kt
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.test
+
+import com.android.modules.testing.utils.ApexInstallHelper
+import com.android.tradefed.invoker.TestInformation
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test
+import com.android.tradefed.testtype.junit4.BeforeClassWithInfo
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.AfterClass
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(DeviceJUnit4ClassRunner::class)
+class ApexUpdateTest : BaseHostJUnit4Test() {
+
+ companion object {
+ private const val APEX_NAME = "com.android.server.pm.test.apex"
+ private const val APK_IN_APEX_NAME = "$APEX_NAME.app"
+ private const val APK_FILE_NAME = "PackageManagerTestApexApp.apk"
+
+ private lateinit var apexInstallHelper: ApexInstallHelper
+
+ @JvmStatic
+ @BeforeClassWithInfo
+ fun initApexHelper(testInformation: TestInformation) {
+ apexInstallHelper = ApexInstallHelper(testInformation)
+ }
+
+ @JvmStatic
+ @AfterClass
+ fun revertChanges() {
+ apexInstallHelper.revertChanges()
+ }
+ }
+
+ @Before
+ @After
+ fun uninstallApp() {
+ device.uninstallPackage(APK_IN_APEX_NAME)
+ }
+
+ @Test
+ fun apexModuleName() {
+ // Install the test APEX and assert it's returned as the APEX module itself
+ // (null when not --include-apex)
+ apexInstallHelper.pushApexAndReboot("PackageManagerTestApex.apex")
+ assertModuleName(APEX_NAME).isNull()
+ assertModuleName(APEX_NAME, includeApex = true).isEqualTo(APEX_NAME)
+
+ // Check the APK-in-APEX, ensuring there is only 1 active package
+ assertModuleName(APK_IN_APEX_NAME).isEqualTo(APEX_NAME)
+ assertModuleName(APK_IN_APEX_NAME, hidden = true).isNull()
+
+ // Then install a /data update to the APK-in-APEX
+ device.installPackage(testInformation.getDependencyFile(APK_FILE_NAME, false), false)
+
+ // Verify same as above
+ assertModuleName(APEX_NAME, includeApex = true).isEqualTo(APEX_NAME)
+ assertModuleName(APK_IN_APEX_NAME).isEqualTo(APEX_NAME)
+
+ // But also check that the /data variant now has a hidden package
+ assertModuleName(APK_IN_APEX_NAME, hidden = true).isEqualTo(APEX_NAME)
+
+ // Reboot the device and check that values are preserved
+ device.reboot()
+ assertModuleName(APEX_NAME, includeApex = true).isEqualTo(APEX_NAME)
+ assertModuleName(APK_IN_APEX_NAME).isEqualTo(APEX_NAME)
+ assertModuleName(APK_IN_APEX_NAME, hidden = true).isEqualTo(APEX_NAME)
+
+ // Revert the install changes (delete system image APEX) and check that it's gone
+ apexInstallHelper.revertChanges()
+ assertModuleName(APEX_NAME, includeApex = true).isNull()
+
+ // Verify the module name is no longer associated with the APK-in-APEX,
+ // which is now just a regular /data APK with no hidden system variant.
+ // The assertion for the valid /data APK uses "null" because the value
+ // printed for normal packages is "apexModuleName=null". As opposed to
+ // a literal null indicating the package variant doesn't exist
+ assertModuleName(APK_IN_APEX_NAME).isEqualTo("null")
+ assertModuleName(APK_IN_APEX_NAME, hidden = true).isEqualTo(null)
+ }
+
+ private fun assertModuleName(
+ packageName: String,
+ hidden: Boolean = false,
+ includeApex: Boolean = false
+ ) = assertThat(
+ device.executeShellCommand(
+ "dumpsys package ${"--include-apex".takeIf { includeApex }} $packageName"
+ )
+ .lineSequence()
+ .map(String::trim)
+ .dropWhile { !it.startsWith(if (hidden) "Hidden system packages:" else "Packages:")}
+ .dropWhile { !it.startsWith("Package [$packageName]") }
+ .takeWhile { !it.startsWith("User 0:") }
+ .firstOrNull { it.startsWith("apexModuleName=") }
+ ?.removePrefix("apexModuleName=")
+ )
+}
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/Apex/Android.bp b/services/tests/PackageManagerServiceTests/host/test-apps/Apex/Android.bp
new file mode 100644
index 0000000..aef365e
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/Apex/Android.bp
@@ -0,0 +1,40 @@
+//
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+apex {
+ name: "PackageManagerTestApex",
+ apps: ["PackageManagerTestApexApp"],
+ androidManifest: "AndroidManifestApex.xml",
+ file_contexts: ":apex.test-file_contexts",
+ key: "apex.test.key",
+ certificate: ":apex.test.certificate",
+ min_sdk_version: "33",
+ installable: true,
+ updatable: true,
+}
+
+android_test_helper_app {
+ name: "PackageManagerTestApexApp",
+ manifest: "AndroidManifestApp.xml",
+ sdk_version: "33",
+ min_sdk_version: "33",
+ apex_available: ["PackageManagerTestApex"],
+ certificate: ":apex.test.certificate",
+}
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/Apex/AndroidManifestApex.xml b/services/tests/PackageManagerServiceTests/host/test-apps/Apex/AndroidManifestApex.xml
new file mode 100644
index 0000000..575b2bc
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/Apex/AndroidManifestApex.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<manifest package="com.android.server.pm.test.apex">
+ <application/>
+</manifest>
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/Apex/AndroidManifestApp.xml b/services/tests/PackageManagerServiceTests/host/test-apps/Apex/AndroidManifestApp.xml
new file mode 100644
index 0000000..87fb5cc
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/Apex/AndroidManifestApp.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<manifest package="com.android.server.pm.test.apex.app">
+ <application/>
+</manifest>
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/Apex/apex_manifest.json b/services/tests/PackageManagerServiceTests/host/test-apps/Apex/apex_manifest.json
new file mode 100644
index 0000000..b89581d
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/Apex/apex_manifest.json
@@ -0,0 +1,4 @@
+{
+ "name": "com.android.server.pm.test.apex",
+ "version": 1
+}
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/AppsFilterImplTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/AppsFilterImplTest.java
index 56cd7a9..7909ba4 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/AppsFilterImplTest.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/AppsFilterImplTest.java
@@ -283,7 +283,7 @@
assertFalse(
appsFilter.shouldFilterApplication(mSnapshot, DUMMY_CALLING_APPID, calling, target,
SYSTEM_USER));
- watcher.verifyNoChangeReported("shouldFilterAplication");
+ watcher.verifyNoChangeReported("shouldFilterApplication");
}
@Test
@@ -1081,7 +1081,7 @@
assertTrue(
appsFilter.shouldFilterApplication(mSnapshot, DUMMY_CALLING_APPID, calling, target,
SYSTEM_USER));
- watcher.verifyNoChangeReported("shouldFilterAplication");
+ watcher.verifyNoChangeReported("shouldFilterApplication");
}
@Test
@@ -1110,7 +1110,36 @@
assertFalse(
appsFilter.shouldFilterApplication(mSnapshot, DUMMY_CALLING_APPID, calling, target,
SYSTEM_USER));
- watcher.verifyNoChangeReported("shouldFilterAplication");
+ watcher.verifyNoChangeReported("shouldFilterApplication");
+ }
+
+ @Test
+ public void testUpdateOwner_DoesntFilter() throws Exception {
+ final AppsFilterImpl appsFilter =
+ new AppsFilterImpl(mFeatureConfigMock, new String[]{}, /* systemAppsQueryable */
+ false, /* overlayProvider */ null, mMockHandler);
+ final WatchableTester watcher = new WatchableTester(appsFilter, "onChange");
+ watcher.register();
+ simulateAddBasicAndroid(appsFilter);
+ watcher.verifyChangeReported("addBasicAndroid");
+ appsFilter.onSystemReady(mPmInternal);
+ watcher.verifyChangeReported("systemReady");
+
+ PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package"),
+ DUMMY_TARGET_APPID);
+ watcher.verifyChangeReported("add package");
+ PackageSetting calling = simulateAddPackage(appsFilter, pkg("com.some.other.package"),
+ DUMMY_CALLING_APPID, withInstallSource(null /* initiatingPackageName */,
+ null /* originatingPackageName */, null /* installerPackageName */,
+ INVALID_UID, target.getPackageName(),
+ null /* installerAttributionTag */,
+ false /* isInitiatingPackageUninstalled */));
+ watcher.verifyChangeReported("add package");
+
+ assertFalse(
+ appsFilter.shouldFilterApplication(mSnapshot, DUMMY_CALLING_APPID, calling, target,
+ SYSTEM_USER));
+ watcher.verifyNoChangeReported("shouldFilterApplication");
}
@Test
@@ -1139,7 +1168,7 @@
assertFalse(
appsFilter.shouldFilterApplication(mSnapshot, DUMMY_TARGET_APPID, target,
instrumentation, SYSTEM_USER));
- watcher.verifyNoChangeReported("shouldFilterAplication");
+ watcher.verifyNoChangeReported("shouldFilterApplication");
}
@Test
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt
index 8e1ca3c..0b7020c7 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt
@@ -218,6 +218,7 @@
AndroidPackage::isAllowClearUserDataOnFailedRestore,
AndroidPackage::isAllowNativeHeapPointerTagging,
AndroidPackage::isAllowTaskReparenting,
+ AndroidPackage::isAllowUpdateOwnership,
AndroidPackage::isBackupInForeground,
AndroidPackage::isHardwareAccelerated,
AndroidPackage::isCantSaveState,
diff --git a/services/tests/RemoteProvisioningServiceTests/src/com/android/server/security/rkp/RemoteProvisioningRegistrationTest.java b/services/tests/RemoteProvisioningServiceTests/src/com/android/server/security/rkp/RemoteProvisioningRegistrationTest.java
index 470f2be..7b361d3 100644
--- a/services/tests/RemoteProvisioningServiceTests/src/com/android/server/security/rkp/RemoteProvisioningRegistrationTest.java
+++ b/services/tests/RemoteProvisioningServiceTests/src/com/android/server/security/rkp/RemoteProvisioningRegistrationTest.java
@@ -34,7 +34,9 @@
import android.os.CancellationSignal;
import android.os.OperationCanceledException;
import android.os.OutcomeReceiver;
+import android.os.RemoteException;
import android.security.rkp.IGetKeyCallback;
+import android.security.rkp.IStoreUpgradedKeyCallback;
import android.security.rkp.service.RegistrationProxy;
import android.security.rkp.service.RemotelyProvisionedKey;
@@ -72,6 +74,12 @@
return answerVoid(answer);
}
+ // answerVoid wrapper for mocking storeUpgradeKeyAsync.
+ static Answer<Void> answerStoreUpgradedKeyAsync(
+ VoidAnswer4<byte[], byte[], Executor, OutcomeReceiver<Void, Exception>> answer) {
+ return answerVoid(answer);
+ }
+
// matcher helper, making it easier to match the different key types
private android.security.rkp.RemotelyProvisionedKey matches(
RemotelyProvisionedKey expectedKey) {
@@ -178,16 +186,63 @@
@Test
public void storeUpgradedKeySuccess() throws Exception {
- // TODO(b/262748535)
+ doAnswer(
+ answerStoreUpgradedKeyAsync((oldBlob, newBlob, executor, receiver) ->
+ executor.execute(() -> receiver.onResult(null))))
+ .when(mRegistrationProxy)
+ .storeUpgradedKeyAsync(any(), any(), any(), any());
+
+ IStoreUpgradedKeyCallback callback = mock(IStoreUpgradedKeyCallback.class);
+ mRegistration.storeUpgradedKeyAsync(new byte[0], new byte[0], callback);
+ verify(callback).onSuccess();
+ verifyNoMoreInteractions(callback);
}
@Test
public void storeUpgradedKeyFails() throws Exception {
- // TODO(b/262748535)
+ final String errorString = "this is a failure";
+ doAnswer(
+ answerStoreUpgradedKeyAsync((oldBlob, newBlob, executor, receiver) ->
+ executor.execute(() -> receiver.onError(new RemoteException(errorString)))))
+ .when(mRegistrationProxy)
+ .storeUpgradedKeyAsync(any(), any(), any(), any());
+
+ IStoreUpgradedKeyCallback callback = mock(IStoreUpgradedKeyCallback.class);
+ mRegistration.storeUpgradedKeyAsync(new byte[0], new byte[0], callback);
+ verify(callback).onError(errorString);
+ verifyNoMoreInteractions(callback);
}
@Test
- public void storeUpgradedCatchesExceptionFromProxy() throws Exception {
- // TODO(b/262748535)
+ public void storeUpgradedKeyHandlesException() throws Exception {
+ final String errorString = "all aboard the failboat, toot toot";
+ doThrow(new IllegalArgumentException(errorString))
+ .when(mRegistrationProxy)
+ .storeUpgradedKeyAsync(any(), any(), any(), any());
+
+ IStoreUpgradedKeyCallback callback = mock(IStoreUpgradedKeyCallback.class);
+ mRegistration.storeUpgradedKeyAsync(new byte[0], new byte[0], callback);
+ verify(callback).onError(errorString);
+ verifyNoMoreInteractions(callback);
}
+
+ @Test
+ public void storeUpgradedKeyDuplicateCallback() throws Exception {
+ IStoreUpgradedKeyCallback callback = mock(IStoreUpgradedKeyCallback.class);
+
+ doAnswer(
+ answerStoreUpgradedKeyAsync((oldBlob, newBlob, executor, receiver) -> {
+ assertThrows(IllegalArgumentException.class,
+ () -> mRegistration.storeUpgradedKeyAsync(new byte[0], new byte[0],
+ callback));
+ executor.execute(() -> receiver.onResult(null));
+ }))
+ .when(mRegistrationProxy)
+ .storeUpgradedKeyAsync(any(), any(), any(), any());
+
+ mRegistration.storeUpgradedKeyAsync(new byte[0], new byte[0], callback);
+ verify(callback).onSuccess();
+ verifyNoMoreInteractions(callback);
+ }
+
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
index 77127c5..92570aa 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
@@ -22,7 +22,6 @@
import static com.android.server.am.BroadcastProcessQueue.REASON_CONTAINS_MANIFEST;
import static com.android.server.am.BroadcastProcessQueue.REASON_CONTAINS_ORDERED;
import static com.android.server.am.BroadcastProcessQueue.REASON_CONTAINS_PRIORITIZED;
-import static com.android.server.am.BroadcastProcessQueue.REASON_CONTAINS_RESULT_TO;
import static com.android.server.am.BroadcastProcessQueue.insertIntoRunnableList;
import static com.android.server.am.BroadcastProcessQueue.removeFromRunnableList;
import static com.android.server.am.BroadcastQueueTest.CLASS_BLUE;
@@ -115,8 +114,29 @@
mConstants.DELAY_NORMAL_MILLIS = 10_000;
mConstants.DELAY_CACHED_MILLIS = 120_000;
+ final BroadcastSkipPolicy emptySkipPolicy = new BroadcastSkipPolicy(mAms) {
+ public boolean shouldSkip(BroadcastRecord r, Object o) {
+ // Ignored
+ return false;
+ }
+ public String shouldSkipMessage(BroadcastRecord r, Object o) {
+ // Ignored
+ return null;
+ }
+ public boolean disallowBackgroundStart(BroadcastRecord r) {
+ // Ignored
+ return false;
+ }
+ };
+ final BroadcastHistory emptyHistory = new BroadcastHistory(mConstants) {
+ public void addBroadcastToHistoryLocked(BroadcastRecord original) {
+ // Ignored
+ }
+ };
+
+
mImpl = new BroadcastQueueModernImpl(mAms, mHandlerThread.getThreadHandler(),
- mConstants, mConstants);
+ mConstants, mConstants, emptySkipPolicy, emptyHistory);
doReturn(1L).when(mQueue1).getRunnableAt();
doReturn(2L).when(mQueue2).getRunnableAt();
@@ -200,7 +220,8 @@
private void enqueueOrReplaceBroadcast(BroadcastProcessQueue queue,
BroadcastRecord record, int recordIndex, long enqueueTime) {
- queue.enqueueOrReplaceBroadcast(record, recordIndex, null /* replacedBroadcastConsumer */);
+ queue.enqueueOrReplaceBroadcast(record, recordIndex,
+ null /* replacedBroadcastConsumer */, false);
record.enqueueTime = enqueueTime;
}
@@ -330,7 +351,8 @@
final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
final BroadcastRecord airplaneRecord = makeBroadcastRecord(airplane,
List.of(makeMockRegisteredReceiver()));
- queue.enqueueOrReplaceBroadcast(airplaneRecord, 0, null /* replacedBroadcastConsumer */);
+ queue.enqueueOrReplaceBroadcast(airplaneRecord, 0,
+ null /* replacedBroadcastConsumer */, false);
queue.setProcessCached(false);
final long notCachedRunnableAt = queue.getRunnableAt();
@@ -352,12 +374,14 @@
// enqueue a bg-priority broadcast then a fg-priority one
final Intent timezone = new Intent(Intent.ACTION_TIMEZONE_CHANGED);
final BroadcastRecord timezoneRecord = makeBroadcastRecord(timezone);
- queue.enqueueOrReplaceBroadcast(timezoneRecord, 0, null /* replacedBroadcastConsumer */);
+ queue.enqueueOrReplaceBroadcast(timezoneRecord, 0,
+ null /* replacedBroadcastConsumer */, false);
final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
airplane.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
final BroadcastRecord airplaneRecord = makeBroadcastRecord(airplane);
- queue.enqueueOrReplaceBroadcast(airplaneRecord, 0, null /* replacedBroadcastConsumer */);
+ queue.enqueueOrReplaceBroadcast(airplaneRecord, 0,
+ null /* replacedBroadcastConsumer */, false);
// verify that:
// (a) the queue is immediately runnable by existence of a fg-priority broadcast
@@ -388,7 +412,8 @@
final BroadcastRecord airplaneRecord = makeBroadcastRecord(airplane, null,
List.of(withPriority(makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN), 10),
withPriority(makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN), 0)), true);
- queue.enqueueOrReplaceBroadcast(airplaneRecord, 1, null /* replacedBroadcastConsumer */);
+ queue.enqueueOrReplaceBroadcast(airplaneRecord, 1,
+ null /* replacedBroadcastConsumer */, false);
assertFalse(queue.isRunnable());
assertEquals(BroadcastProcessQueue.REASON_BLOCKED, queue.getRunnableAtReason());
@@ -411,7 +436,8 @@
final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
final BroadcastRecord airplaneRecord = makeBroadcastRecord(airplane,
List.of(makeMockRegisteredReceiver()));
- queue.enqueueOrReplaceBroadcast(airplaneRecord, 0, null /* replacedBroadcastConsumer */);
+ queue.enqueueOrReplaceBroadcast(airplaneRecord, 0,
+ null /* replacedBroadcastConsumer */, false);
mConstants.MAX_PENDING_BROADCASTS = 128;
queue.invalidateRunnableAt();
@@ -437,11 +463,13 @@
new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED),
List.of(makeMockRegisteredReceiver()));
- queue.enqueueOrReplaceBroadcast(lazyRecord, 0, null /* replacedBroadcastConsumer */);
+ queue.enqueueOrReplaceBroadcast(lazyRecord, 0,
+ null /* replacedBroadcastConsumer */, false);
assertThat(queue.getRunnableAt()).isGreaterThan(lazyRecord.enqueueTime);
assertThat(queue.getRunnableAtReason()).isNotEqualTo(testRunnableAtReason);
- queue.enqueueOrReplaceBroadcast(testRecord, 0, null /* replacedBroadcastConsumer */);
+ queue.enqueueOrReplaceBroadcast(testRecord, 0,
+ null /* replacedBroadcastConsumer */, false);
assertThat(queue.getRunnableAt()).isAtMost(testRecord.enqueueTime);
assertThat(queue.getRunnableAtReason()).isEqualTo(testRunnableAtReason);
}
@@ -459,13 +487,6 @@
}
@Test
- public void testRunnableAt_Cached_ResultTo() {
- final IIntentReceiver resultTo = mock(IIntentReceiver.class);
- doRunnableAt_Cached(makeBroadcastRecord(makeMockIntent(), null,
- List.of(makeMockRegisteredReceiver()), resultTo, false), REASON_CONTAINS_RESULT_TO);
- }
-
- @Test
public void testRunnableAt_Cached_Foreground() {
final Intent foregroundIntent = new Intent();
foregroundIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
@@ -511,25 +532,25 @@
queue.enqueueOrReplaceBroadcast(
makeBroadcastRecord(new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED)
.addFlags(Intent.FLAG_RECEIVER_OFFLOAD)), 0,
- null /* replacedBroadcastConsumer */);
+ null /* replacedBroadcastConsumer */, false);
queue.enqueueOrReplaceBroadcast(
makeBroadcastRecord(new Intent(Intent.ACTION_TIMEZONE_CHANGED)), 0,
- null /* replacedBroadcastConsumer */);
+ null /* replacedBroadcastConsumer */, false);
queue.enqueueOrReplaceBroadcast(
makeBroadcastRecord(new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED)
.addFlags(Intent.FLAG_RECEIVER_FOREGROUND)), 0,
- null /* replacedBroadcastConsumer */);
+ null /* replacedBroadcastConsumer */, false);
queue.enqueueOrReplaceBroadcast(
makeBroadcastRecord(new Intent(Intent.ACTION_ALARM_CHANGED)
.addFlags(Intent.FLAG_RECEIVER_OFFLOAD)), 0,
- null /* replacedBroadcastConsumer */);
+ null /* replacedBroadcastConsumer */, false);
queue.enqueueOrReplaceBroadcast(
makeBroadcastRecord(new Intent(Intent.ACTION_TIME_TICK)), 0,
- null /* replacedBroadcastConsumer */);
+ null /* replacedBroadcastConsumer */, false);
queue.enqueueOrReplaceBroadcast(
makeBroadcastRecord(new Intent(Intent.ACTION_LOCALE_CHANGED)
.addFlags(Intent.FLAG_RECEIVER_FOREGROUND)), 0,
- null /* replacedBroadcastConsumer */);
+ null /* replacedBroadcastConsumer */, false);
queue.makeActiveNextPending();
assertEquals(Intent.ACTION_LOCKED_BOOT_COMPLETED, queue.getActive().intent.getAction());
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
index 8d9dda08..72d8556 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
@@ -92,6 +92,7 @@
import com.android.server.wm.ActivityTaskManagerService;
import org.junit.After;
+import org.junit.Assume;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -357,6 +358,11 @@
}
receiversToSkip.add(o);
}
+ public boolean disallowBackgroundStart(BroadcastRecord r) {
+ // Ignored
+ return false;
+ }
+
}
private class TestInjector extends Injector {
@@ -442,9 +448,9 @@
UnaryOperator<Bundle> extrasOperator, ReceiverInfo info) {
final Intent intent = info.intent;
final Bundle extras = info.extras;
- final boolean ordered = info.ordered;
+ final boolean assumeDelivered = info.assumeDelivered;
mScheduledBroadcasts.add(makeScheduledBroadcast(r, intent));
- if (!wedge && ordered) {
+ if (!wedge && !assumeDelivered) {
assertTrue(r.mReceivers.numberOfCurReceivers() > 0);
assertNotEquals(ProcessList.SCHED_GROUP_UNDEFINED,
mQueue.getPreferredSchedulingGroupLocked(r));
@@ -695,6 +701,7 @@
ArgumentMatcher<String> data,
ArgumentMatcher<Bundle> extras,
Boolean sync,
+ Boolean assumeDelivered,
Integer sendingUser,
Integer processState) {
return (test) -> {
@@ -706,6 +713,7 @@
&& matchObject(data, test.data)
&& matchObject(extras, test.extras)
&& matchElement(sync, test.sync)
+ && matchElement(assumeDelivered, test.assumeDelivered)
&& matchElement(sendingUser, test.sendingUser)
&& matchElement(processState, test.processState);
};
@@ -724,10 +732,12 @@
ArgumentMatcher<String> data,
ArgumentMatcher<Bundle> extras,
Boolean sync,
+ Boolean assumeDelivered,
Integer sendingUser,
Integer processState) {
return argThat(receiverList(manifestReceiverMatcher(intent, activityInfo, compatInfo,
- resultCode, data, extras, sync, sendingUser, processState)));
+ resultCode, data, extras, sync, assumeDelivered,
+ sendingUser, processState)));
}
/**
@@ -743,6 +753,7 @@
ArgumentMatcher<Bundle> extras,
Boolean ordered,
Boolean sticky,
+ Boolean assumeDelivered,
Integer sendingUser,
Integer processState) {
return (test) -> {
@@ -754,6 +765,7 @@
&& matchObject(extras, test.extras)
&& matchElement(ordered, test.ordered)
&& matchElement(sticky, test.sticky)
+ && matchElement(assumeDelivered, test.assumeDelivered)
&& matchElement(sendingUser, test.sendingUser)
&& matchElement(processState, test.processState);
};
@@ -771,10 +783,12 @@
ArgumentMatcher<Bundle> extras,
Boolean ordered,
Boolean sticky,
+ Boolean assumeDelivered,
Integer sendingUser,
Integer processState) {
return argThat(receiverList(registeredReceiverMatcher(receiver, intent, resultCode,
- data, extras, ordered, sticky, sendingUser, processState)));
+ data, extras, ordered, sticky, assumeDelivered,
+ sendingUser, processState)));
}
/**
@@ -827,36 +841,36 @@
final Intent targetedIntent = new Intent(intent);
targetedIntent.setComponent(component);
verify(app.getThread(), mode).scheduleReceiverList(
- manifestReceiver(filterEquals(targetedIntent),
- null, null, null, null, null, null, UserHandle.USER_SYSTEM, null));
+ manifestReceiver(filterEquals(targetedIntent),
+ null, null, null, null, null, null, null, UserHandle.USER_SYSTEM, null));
}
private void verifyScheduleReceiver(VerificationMode mode, ProcessRecord app,
Intent intent, int userId) throws Exception {
verify(app.getThread(), mode).scheduleReceiverList(
- manifestReceiver(filterEqualsIgnoringComponent(intent),
- null, null, null, null, null, null, userId, null));
+ manifestReceiver(filterEqualsIgnoringComponent(intent),
+ null, null, null, null, null, null, null, userId, null));
}
private void verifyScheduleReceiver(VerificationMode mode, ProcessRecord app,
int userId) throws Exception {
verify(app.getThread(), mode).scheduleReceiverList(
manifestReceiver(null,
- null, null, null, null, null, null, userId, null));
+ null, null, null, null, null, null, null, userId, null));
}
private void verifyScheduleRegisteredReceiver(ProcessRecord app,
Intent intent) throws Exception {
verify(app.getThread()).scheduleReceiverList(
- registeredReceiver(null, filterEqualsIgnoringComponent(intent),
- null, null, null, null, null, UserHandle.USER_SYSTEM, null));
+ registeredReceiver(null, filterEqualsIgnoringComponent(intent),
+ null, null, null, null, null, null, UserHandle.USER_SYSTEM, null));
}
private void verifyScheduleRegisteredReceiver(VerificationMode mode, ProcessRecord app,
int userId) throws Exception {
verify(app.getThread(), mode).scheduleReceiverList(
registeredReceiver(null, null,
- null, null, null, null, null, userId, null));
+ null, null, null, null, null, null, userId, null));
}
static final int USER_GUEST = 11;
@@ -1112,10 +1126,11 @@
}
/**
- * Verify that we detect and ANR a wedged process.
+ * Verify that we detect and ANR a wedged process when delivering to a
+ * manifest receiver.
*/
@Test
- public void testWedged() throws Exception {
+ public void testWedged_Manifest() throws Exception {
final ProcessRecord callerApp = makeActiveProcessRecord(PACKAGE_RED);
final ProcessRecord receiverApp = makeActiveProcessRecord(PACKAGE_GREEN,
ProcessBehavior.WEDGE);
@@ -1129,6 +1144,77 @@
}
/**
+ * Verify that we detect and ANR a wedged process when delivering an ordered
+ * broadcast, and that we deliver final result.
+ */
+ @Test
+ public void testWedged_Registered_Ordered() throws Exception {
+ // Legacy stack doesn't detect these ANRs; likely an oversight
+ Assume.assumeTrue(mImpl == Impl.MODERN);
+
+ final ProcessRecord callerApp = makeActiveProcessRecord(PACKAGE_RED);
+ final ProcessRecord receiverApp = makeActiveProcessRecord(PACKAGE_GREEN,
+ ProcessBehavior.WEDGE);
+
+ final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+ final IIntentReceiver resultTo = mock(IIntentReceiver.class);
+ enqueueBroadcast(makeOrderedBroadcastRecord(airplane, callerApp,
+ List.of(makeRegisteredReceiver(receiverApp)), resultTo, null));
+
+ waitForIdle();
+ verify(mAms).appNotResponding(eq(receiverApp), any());
+ verifyScheduleRegisteredReceiver(callerApp, airplane);
+ }
+
+ /**
+ * Verify that we detect and ANR a wedged process when delivering an
+ * unordered broadcast with a {@code resultTo}.
+ */
+ @Test
+ public void testWedged_Registered_ResultTo() throws Exception {
+ // Legacy stack doesn't detect these ANRs; likely an oversight
+ Assume.assumeTrue(mImpl == Impl.MODERN);
+
+ final ProcessRecord callerApp = makeActiveProcessRecord(PACKAGE_RED);
+ final ProcessRecord receiverApp = makeActiveProcessRecord(PACKAGE_GREEN,
+ ProcessBehavior.WEDGE);
+
+ final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+ final IIntentReceiver resultTo = mock(IIntentReceiver.class);
+ enqueueBroadcast(makeBroadcastRecord(airplane, callerApp,
+ List.of(makeRegisteredReceiver(receiverApp)), resultTo));
+
+ waitForIdle();
+ verify(mAms).appNotResponding(eq(receiverApp), any());
+ verifyScheduleRegisteredReceiver(callerApp, airplane);
+ }
+
+ /**
+ * Verify that we detect and ANR a wedged process when delivering a
+ * broadcast with more than one priority tranche.
+ */
+ @Test
+ public void testWedged_Registered_Prioritized() throws Exception {
+ // Legacy stack doesn't detect these ANRs; likely an oversight
+ Assume.assumeTrue(mImpl == Impl.MODERN);
+
+ final ProcessRecord callerApp = makeActiveProcessRecord(PACKAGE_RED);
+ final ProcessRecord receiverGreenApp = makeActiveProcessRecord(PACKAGE_GREEN,
+ ProcessBehavior.WEDGE);
+ final ProcessRecord receiverBlueApp = makeActiveProcessRecord(PACKAGE_BLUE,
+ ProcessBehavior.NORMAL);
+
+ final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+ enqueueBroadcast(makeBroadcastRecord(airplane, callerApp,
+ List.of(makeRegisteredReceiver(receiverGreenApp, 10),
+ makeRegisteredReceiver(receiverBlueApp, 5))));
+
+ waitForIdle();
+ verify(mAms).appNotResponding(eq(receiverGreenApp), any());
+ verifyScheduleRegisteredReceiver(receiverBlueApp, airplane);
+ }
+
+ /**
* Verify that we handle registered receivers in a process that always
* responds with {@link DeadObjectException}, recovering to restart the
* process and deliver their next broadcast.
@@ -1338,11 +1424,11 @@
// Confirm that we saw no registered receiver traffic
final IApplicationThread oldThread = oldApp.getThread();
- verify(oldThread, never()).scheduleRegisteredReceiver(any(),
- any(), anyInt(), any(), any(), anyBoolean(), anyBoolean(), anyInt(), anyInt());
+ verify(oldThread, never()).scheduleRegisteredReceiver(any(), any(), anyInt(), any(), any(),
+ anyBoolean(), anyBoolean(), anyBoolean(), anyInt(), anyInt());
final IApplicationThread newThread = newApp.getThread();
- verify(newThread, never()).scheduleRegisteredReceiver(any(),
- any(), anyInt(), any(), any(), anyBoolean(), anyBoolean(), anyInt(), anyInt());
+ verify(newThread, never()).scheduleRegisteredReceiver(any(), any(), anyInt(), any(), any(),
+ anyBoolean(), anyBoolean(), anyBoolean(), anyInt(), anyInt());
// Confirm that we saw final manifest broadcast
verifyScheduleReceiver(times(1), newApp, airplane,
@@ -1464,22 +1550,22 @@
expectedExtras.putBoolean(PACKAGE_RED, true);
inOrder.verify(greenThread).scheduleReceiverList(manifestReceiver(
filterEqualsIgnoringComponent(airplane), null, null,
- Activity.RESULT_OK, null, bundleEquals(expectedExtras), true,
+ Activity.RESULT_OK, null, bundleEquals(expectedExtras), true, false,
UserHandle.USER_SYSTEM, null));
inOrder.verify(blueThread).scheduleReceiverList(manifestReceiver(
filterEqualsIgnoringComponent(airplane), null, null,
- Activity.RESULT_OK, null, bundleEquals(expectedExtras), true,
+ Activity.RESULT_OK, null, bundleEquals(expectedExtras), true, false,
UserHandle.USER_SYSTEM, null));
expectedExtras.putBoolean(PACKAGE_BLUE, true);
inOrder.verify(yellowThread).scheduleReceiverList(manifestReceiver(
filterEqualsIgnoringComponent(airplane), null, null,
- Activity.RESULT_OK, null, bundleEquals(expectedExtras), true,
+ Activity.RESULT_OK, null, bundleEquals(expectedExtras), true, false,
UserHandle.USER_SYSTEM, null));
expectedExtras.putBoolean(PACKAGE_YELLOW, true);
inOrder.verify(redThread).scheduleReceiverList(registeredReceiver(
null, filterEquals(airplane),
Activity.RESULT_OK, null, bundleEquals(expectedExtras), false,
- null, UserHandle.USER_SYSTEM, null));
+ null, true, UserHandle.USER_SYSTEM, null));
// Finally, verify that we thawed the final receiver
verify(mAms.mOomAdjuster.mCachedAppOptimizer).unfreezeTemporarily(eq(callerApp),
@@ -1544,22 +1630,22 @@
final InOrder inOrder = inOrder(greenThread, blueThread, redThread);
inOrder.verify(greenThread).scheduleReceiverList(manifestReceiver(
filterEqualsIgnoringComponent(intent), null, null,
- Activity.RESULT_OK, null, null, true, UserHandle.USER_SYSTEM,
+ Activity.RESULT_OK, null, null, true, false, UserHandle.USER_SYSTEM,
null));
if ((intent.getFlags() & Intent.FLAG_RECEIVER_NO_ABORT) != 0) {
inOrder.verify(blueThread).scheduleReceiverList(manifestReceiver(
filterEqualsIgnoringComponent(intent), null, null,
- Activity.RESULT_OK, null, null, true, UserHandle.USER_SYSTEM,
+ Activity.RESULT_OK, null, null, true, false, UserHandle.USER_SYSTEM,
null));
} else {
inOrder.verify(blueThread, never()).scheduleReceiverList(manifestReceiver(
- null, null, null, null,
+ null, null, null, null, null,
null, null, null, null, null));
}
inOrder.verify(redThread).scheduleReceiverList(registeredReceiver(
null, filterEquals(intent),
Activity.RESULT_OK, null, bundleEquals(expectedExtras),
- false, null, UserHandle.USER_SYSTEM, null));
+ false, null, true, UserHandle.USER_SYSTEM, null));
}
/**
@@ -1582,7 +1668,7 @@
verify(callerThread).scheduleReceiverList(registeredReceiver(
null, filterEquals(airplane),
Activity.RESULT_OK, null, bundleEquals(orderedExtras), false,
- null, UserHandle.USER_SYSTEM, null));
+ null, true, UserHandle.USER_SYSTEM, null));
}
/**
@@ -1603,7 +1689,7 @@
verify(callerThread).scheduleReceiverList(registeredReceiver(
null, filterEquals(airplane),
Activity.RESULT_OK, null, null, false,
- null, UserHandle.USER_SYSTEM, null));
+ null, true, UserHandle.USER_SYSTEM, null));
}
/**
@@ -1768,26 +1854,26 @@
// First broadcast is canceled
inOrder.verify(callerThread).scheduleReceiverList(registeredReceiver(null,
filterAndExtrasEquals(timezoneFirst), Activity.RESULT_CANCELED, null,
- null, false, null, UserHandle.USER_SYSTEM, null));
+ null, false, null, true, UserHandle.USER_SYSTEM, null));
// We deliver second broadcast to app
timezoneSecond.setClassName(PACKAGE_BLUE, CLASS_GREEN);
inOrder.verify(blueThread).scheduleReceiverList(manifestReceiver(
filterAndExtrasEquals(timezoneSecond),
- null, null, null, null, null, true, null, null));
+ null, null, null, null, null, true, false, null, null));
// Second broadcast is finished
timezoneSecond.setComponent(null);
inOrder.verify(callerThread).scheduleReceiverList(registeredReceiver(null,
filterAndExtrasEquals(timezoneSecond), Activity.RESULT_OK, null,
- null, false, null, UserHandle.USER_SYSTEM, null));
+ null, false, null, true, UserHandle.USER_SYSTEM, null));
// Since we "replaced" the first broadcast in its original position,
// only now do we see the airplane broadcast
airplane.setClassName(PACKAGE_BLUE, CLASS_RED);
inOrder.verify(blueThread).scheduleReceiverList(manifestReceiver(
filterEquals(airplane),
- null, null, null, null, null, false, null, null));
+ null, null, null, null, null, false, false, null, null));
}
@Test
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index 9234431..c40017a 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -2452,7 +2452,7 @@
if (record == null) {
record = makeServiceRecord(service);
}
- AppBindRecord binding = new AppBindRecord(record, null, client);
+ AppBindRecord binding = new AppBindRecord(record, null, client, null);
ConnectionRecord cr = spy(new ConnectionRecord(binding,
mock(ActivityServiceConnectionsHolder.class),
mock(IServiceConnection.class), bindFlags,
diff --git a/services/tests/mockingservicestests/src/com/android/server/companion/virtual/CameraAccessControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/companion/virtual/CameraAccessControllerTest.java
index 757d27b..f6566a0d 100644
--- a/services/tests/mockingservicestests/src/com/android/server/companion/virtual/CameraAccessControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/companion/virtual/CameraAccessControllerTest.java
@@ -39,6 +39,7 @@
import android.hardware.camera2.CameraManager;
import android.os.Process;
import android.os.UserManager;
+import android.platform.test.annotations.Presubmit;
import android.testing.TestableContext;
import android.util.ArraySet;
@@ -59,6 +60,7 @@
import java.util.ArrayList;
import java.util.List;
+@Presubmit
@RunWith(AndroidJUnit4.class)
public class CameraAccessControllerTest {
private static final String FRONT_CAMERA = "0";
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/JobConcurrencyManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/JobConcurrencyManagerTest.java
index 79fbc87..7e1a42b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/JobConcurrencyManagerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/JobConcurrencyManagerTest.java
@@ -213,7 +213,7 @@
mJobConcurrencyManager.prepareForAssignmentDeterminationLocked(
idle, preferredUidOnly, stoppable, assignmentInfo);
- assertEquals(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT, idle.size());
+ assertEquals(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT, idle.size());
assertEquals(0, preferredUidOnly.size());
assertEquals(0, stoppable.size());
assertEquals(0, assignmentInfo.minPreferredUidOnlyWaitingTimeMs);
@@ -222,7 +222,7 @@
@Test
public void testPrepareForAssignmentDetermination_onlyPendingJobs() {
- for (int i = 0; i < JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT; ++i) {
+ for (int i = 0; i < JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT; ++i) {
JobStatus job = createJob(mDefaultUserId * UserHandle.PER_USER_RANGE + i);
mPendingJobQueue.add(job);
}
@@ -235,7 +235,7 @@
mJobConcurrencyManager.prepareForAssignmentDeterminationLocked(
idle, preferredUidOnly, stoppable, assignmentInfo);
- assertEquals(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT, idle.size());
+ assertEquals(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT, idle.size());
assertEquals(0, preferredUidOnly.size());
assertEquals(0, stoppable.size());
assertEquals(0, assignmentInfo.minPreferredUidOnlyWaitingTimeMs);
@@ -244,7 +244,7 @@
@Test
public void testPrepareForAssignmentDetermination_onlyPreferredUidOnly() {
- for (int i = 0; i < JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT; ++i) {
+ for (int i = 0; i < JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT; ++i) {
JobStatus job = createJob(mDefaultUserId * UserHandle.PER_USER_RANGE + i);
mJobConcurrencyManager.addRunningJobForTesting(job);
}
@@ -262,7 +262,7 @@
idle, preferredUidOnly, stoppable, assignmentInfo);
assertEquals(0, idle.size());
- assertEquals(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT, preferredUidOnly.size());
+ assertEquals(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT, preferredUidOnly.size());
assertEquals(0, stoppable.size());
assertEquals(0, assignmentInfo.minPreferredUidOnlyWaitingTimeMs);
assertEquals(0, assignmentInfo.numRunningImmediacyPrivileged);
@@ -270,7 +270,7 @@
@Test
public void testPrepareForAssignmentDetermination_onlyStartedWithImmediacyPrivilege() {
- for (int i = 0; i < JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT; ++i) {
+ for (int i = 0; i < JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT; ++i) {
JobStatus job = createJob(mDefaultUserId * UserHandle.PER_USER_RANGE + i);
job.startedWithImmediacyPrivilege = true;
mJobConcurrencyManager.addRunningJobForTesting(job);
@@ -289,19 +289,19 @@
idle, preferredUidOnly, stoppable, assignmentInfo);
assertEquals(0, idle.size());
- assertEquals(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT / 2, preferredUidOnly.size());
- assertEquals(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT / 2, stoppable.size());
+ assertEquals(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT / 2, preferredUidOnly.size());
+ assertEquals(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT / 2, stoppable.size());
assertEquals(0, assignmentInfo.minPreferredUidOnlyWaitingTimeMs);
- assertEquals(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT,
+ assertEquals(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT,
assignmentInfo.numRunningImmediacyPrivileged);
}
@Test
public void testDetermineAssignments_allRegular() throws Exception {
- setConcurrencyConfig(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT,
- new TypeConfig(WORK_TYPE_BG, 0, JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT));
+ setConcurrencyConfig(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT,
+ new TypeConfig(WORK_TYPE_BG, 0, JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT));
final ArraySet<JobStatus> jobs = new ArraySet<>();
- for (int i = 0; i < JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT; ++i) {
+ for (int i = 0; i < JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT; ++i) {
final int uid = mDefaultUserId * UserHandle.PER_USER_RANGE + i;
final String sourcePkgName = "com.source.package." + UserHandle.getAppId(uid);
setPackageUid(sourcePkgName, uid);
@@ -322,7 +322,7 @@
.determineAssignmentsLocked(changed, idle, preferredUidOnly, stoppable,
assignmentInfo);
- assertEquals(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT, changed.size());
+ assertEquals(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT, changed.size());
for (int i = changed.size() - 1; i >= 0; --i) {
jobs.remove(changed.valueAt(i).newJob);
}
@@ -332,16 +332,16 @@
@Test
public void testDetermineAssignments_allPreferredUidOnly_shortTimeLeft() throws Exception {
mConfigBuilder.setBoolean(JobConcurrencyManager.KEY_ENABLE_MAX_WAIT_TIME_BYPASS, true);
- setConcurrencyConfig(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT,
- new TypeConfig(WORK_TYPE_BG, 0, JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT));
- for (int i = 0; i < JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT * 2; ++i) {
+ setConcurrencyConfig(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT,
+ new TypeConfig(WORK_TYPE_BG, 0, JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT));
+ for (int i = 0; i < JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT * 2; ++i) {
final int uid = mDefaultUserId * UserHandle.PER_USER_RANGE + i;
final String sourcePkgName = "com.source.package." + UserHandle.getAppId(uid);
setPackageUid(sourcePkgName, uid);
final JobStatus job = createJob(uid, sourcePkgName);
spyOn(job);
doReturn(i % 2 == 0).when(job).shouldTreatAsExpeditedJob();
- if (i < JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT) {
+ if (i < JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT) {
mJobConcurrencyManager.addRunningJobForTesting(job);
} else {
mPendingJobQueue.add(job);
@@ -366,30 +366,30 @@
mJobConcurrencyManager.prepareForAssignmentDeterminationLocked(
idle, preferredUidOnly, stoppable, assignmentInfo);
assertEquals(remainingTimeMs, assignmentInfo.minPreferredUidOnlyWaitingTimeMs);
- assertEquals(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT, preferredUidOnly.size());
+ assertEquals(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT, preferredUidOnly.size());
mJobConcurrencyManager
.determineAssignmentsLocked(changed, idle, preferredUidOnly, stoppable,
assignmentInfo);
- assertEquals(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT, preferredUidOnly.size());
+ assertEquals(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT, preferredUidOnly.size());
assertEquals(0, changed.size());
}
@Test
public void testDetermineAssignments_allPreferredUidOnly_mediumTimeLeft() throws Exception {
mConfigBuilder.setBoolean(JobConcurrencyManager.KEY_ENABLE_MAX_WAIT_TIME_BYPASS, true);
- setConcurrencyConfig(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT,
- new TypeConfig(WORK_TYPE_BG, 0, JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT));
+ setConcurrencyConfig(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT,
+ new TypeConfig(WORK_TYPE_BG, 0, JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT));
final ArraySet<JobStatus> jobs = new ArraySet<>();
- for (int i = 0; i < JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT * 2; ++i) {
+ for (int i = 0; i < JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT * 2; ++i) {
final int uid = mDefaultUserId * UserHandle.PER_USER_RANGE + i;
final String sourcePkgName = "com.source.package." + UserHandle.getAppId(uid);
setPackageUid(sourcePkgName, uid);
final JobStatus job = createJob(uid, sourcePkgName);
spyOn(job);
doReturn(i % 2 == 0).when(job).shouldTreatAsExpeditedJob();
- if (i < JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT) {
+ if (i < JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT) {
mJobConcurrencyManager.addRunningJobForTesting(job);
} else {
mPendingJobQueue.add(job);
@@ -417,17 +417,17 @@
mJobConcurrencyManager.prepareForAssignmentDeterminationLocked(
idle, preferredUidOnly, stoppable, assignmentInfo);
assertEquals(remainingTimeMs, assignmentInfo.minPreferredUidOnlyWaitingTimeMs);
- assertEquals(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT, preferredUidOnly.size());
+ assertEquals(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT, preferredUidOnly.size());
mJobConcurrencyManager
.determineAssignmentsLocked(changed, idle, preferredUidOnly, stoppable,
assignmentInfo);
- assertEquals(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT, preferredUidOnly.size());
+ assertEquals(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT, preferredUidOnly.size());
for (int i = changed.size() - 1; i >= 0; --i) {
jobs.remove(changed.valueAt(i).newJob);
}
- assertEquals(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT - 1, jobs.size());
+ assertEquals(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT - 1, jobs.size());
assertEquals(1, changed.size());
JobStatus assignedJob = changed.valueAt(0).newJob;
assertTrue(assignedJob.shouldTreatAsExpeditedJob());
@@ -436,17 +436,17 @@
@Test
public void testDetermineAssignments_allPreferredUidOnly_longTimeLeft() throws Exception {
mConfigBuilder.setBoolean(JobConcurrencyManager.KEY_ENABLE_MAX_WAIT_TIME_BYPASS, true);
- setConcurrencyConfig(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT,
- new TypeConfig(WORK_TYPE_BG, 0, JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT));
+ setConcurrencyConfig(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT,
+ new TypeConfig(WORK_TYPE_BG, 0, JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT));
final ArraySet<JobStatus> jobs = new ArraySet<>();
- for (int i = 0; i < JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT * 2; ++i) {
+ for (int i = 0; i < JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT * 2; ++i) {
final int uid = mDefaultUserId * UserHandle.PER_USER_RANGE + i;
final String sourcePkgName = "com.source.package." + UserHandle.getAppId(uid);
setPackageUid(sourcePkgName, uid);
final JobStatus job = createJob(uid, sourcePkgName);
spyOn(job);
doReturn(i % 2 == 0).when(job).shouldTreatAsExpeditedJob();
- if (i < JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT) {
+ if (i < JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT) {
mJobConcurrencyManager.addRunningJobForTesting(job);
} else {
mPendingJobQueue.add(job);
@@ -473,13 +473,13 @@
mJobConcurrencyManager.prepareForAssignmentDeterminationLocked(
idle, preferredUidOnly, stoppable, assignmentInfo);
assertEquals(remainingTimeMs, assignmentInfo.minPreferredUidOnlyWaitingTimeMs);
- assertEquals(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT, preferredUidOnly.size());
+ assertEquals(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT, preferredUidOnly.size());
mJobConcurrencyManager
.determineAssignmentsLocked(changed, idle, preferredUidOnly, stoppable,
assignmentInfo);
- assertEquals(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT, preferredUidOnly.size());
+ assertEquals(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT, preferredUidOnly.size());
// Depending on iteration order, we may create 1 or 2 contexts.
final long numAssignedJobs = changed.size();
assertTrue(numAssignedJobs > 0);
@@ -488,7 +488,7 @@
jobs.remove(changed.valueAt(i).newJob);
}
assertEquals(numAssignedJobs,
- JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT - jobs.size());
+ JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT - jobs.size());
JobStatus firstAssignedJob = changed.valueAt(0).newJob;
if (!firstAssignedJob.shouldTreatAsExpeditedJob()) {
assertEquals(2, numAssignedJobs);
@@ -538,14 +538,14 @@
assertFalse(mJobConcurrencyManager.isPkgConcurrencyLimitedLocked(topJob));
// Pending jobs shouldn't affect TOP job's status.
- for (int i = 1; i <= JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT; ++i) {
+ for (int i = 1; i <= JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT; ++i) {
final JobStatus job = createJob(mDefaultUserId * UserHandle.PER_USER_RANGE + i);
mPendingJobQueue.add(job);
}
assertFalse(mJobConcurrencyManager.isPkgConcurrencyLimitedLocked(topJob));
// Already running jobs shouldn't affect TOP job's status.
- for (int i = 1; i <= JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT; ++i) {
+ for (int i = 1; i <= JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT; ++i) {
final JobStatus job = createJob(mDefaultUserId * UserHandle.PER_USER_RANGE, i);
mJobConcurrencyManager.addRunningJobForTesting(job);
}
@@ -605,9 +605,9 @@
spyOn(testEj);
doReturn(true).when(testEj).shouldTreatAsExpeditedJob();
- setConcurrencyConfig(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT);
+ setConcurrencyConfig(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT);
- for (int i = 0; i < JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT; ++i) {
+ for (int i = 0; i < JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT; ++i) {
final JobStatus job = createJob(mDefaultUserId * UserHandle.PER_USER_RANGE + i, i + 1);
mPendingJobQueue.add(job);
}
@@ -887,12 +887,14 @@
mConfigBuilder
.setInt(WorkTypeConfig.KEY_PREFIX_MAX_TOTAL + identifier, total);
for (TypeConfig config : typeConfigs) {
- mConfigBuilder.setInt(
- WorkTypeConfig.KEY_PREFIX_MAX + config.workTypeString + "_" + identifier,
- config.max);
- mConfigBuilder.setInt(
- WorkTypeConfig.KEY_PREFIX_MIN + config.workTypeString + "_" + identifier,
- config.min);
+ mConfigBuilder.setFloat(
+ WorkTypeConfig.KEY_PREFIX_MAX_RATIO + config.workTypeString + "_"
+ + identifier,
+ (float) config.max / total);
+ mConfigBuilder.setFloat(
+ WorkTypeConfig.KEY_PREFIX_MIN_RATIO + config.workTypeString + "_"
+ + identifier,
+ (float) config.min / total);
}
}
updateDeviceConfig();
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java
index 2f909aa..5b0e2f3 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java
@@ -518,6 +518,7 @@
apexInfo.isActive = isActive;
apexInfo.isFactory = isFactory;
apexInfo.modulePath = apexFile.getPath();
+ apexInfo.preinstalledModulePath = apexFile.getPath();
return apexInfo;
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/BackgroundDexOptServiceUnitTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/BackgroundDexOptServiceUnitTest.java
index 8b36da5..d5aa7fe 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/BackgroundDexOptServiceUnitTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/BackgroundDexOptServiceUnitTest.java
@@ -413,8 +413,8 @@
mDexOptThread.join(TEST_WAIT_TIMEOUT_MS);
mCancelThread.join(TEST_WAIT_TIMEOUT_MS);
- // Always reschedule for periodic job
- verify(mJobServiceForIdle).jobFinished(mJobParametersForIdle, false);
+ // The job should be rescheduled.
+ verify(mJobServiceForIdle).jobFinished(mJobParametersForIdle, true /* wantsReschedule */);
verifyLastControlDexOptBlockingCall(false);
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java
index 1367af8..f13de12 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java
@@ -20,25 +20,31 @@
import static com.google.common.truth.Truth.assertWithMessage;
+import static org.mockito.Mockito.any;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.annotation.UserIdInt;
import android.app.ActivityManagerInternal;
import android.content.Context;
+import android.content.pm.PackageManagerInternal;
import android.content.pm.UserInfo;
import android.os.UserHandle;
import android.os.UserManager;
+import android.os.storage.StorageManager;
+import android.provider.Settings;
import android.util.Log;
import android.util.SparseArray;
import androidx.test.annotation.UiThreadTest;
import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder;
+import com.android.internal.widget.LockSettingsInternal;
import com.android.server.ExtendedMockitoTestCase;
import com.android.server.LocalServices;
import com.android.server.am.UserState;
import com.android.server.pm.UserManagerService.UserData;
+import com.android.server.storage.DeviceStorageMonitorInternal;
import org.junit.After;
import org.junit.Before;
@@ -86,6 +92,10 @@
private @Mock PackageManagerService mMockPms;
private @Mock UserDataPreparer mMockUserDataPreparer;
private @Mock ActivityManagerInternal mActivityManagerInternal;
+ private @Mock DeviceStorageMonitorInternal mDeviceStorageMonitorInternal;
+ private @Mock StorageManager mStorageManager;
+ private @Mock LockSettingsInternal mLockSettingsInternal;
+ private @Mock PackageManagerInternal mPackageManagerInternal;
/**
* Reference to the {@link UserManagerService} being tested.
@@ -101,7 +111,8 @@
protected void initializeSession(StaticMockitoSessionBuilder builder) {
builder
.spyStatic(UserManager.class)
- .spyStatic(LocalServices.class);
+ .spyStatic(LocalServices.class)
+ .mockStatic(Settings.Global.class);
}
@Before
@@ -112,6 +123,14 @@
// Called when WatchedUserStates is constructed
doNothing().when(() -> UserManager.invalidateIsUserUnlockedCache());
+ // Called when creating new users
+ when(mDeviceStorageMonitorInternal.isMemoryLow()).thenReturn(false);
+ mockGetLocalService(DeviceStorageMonitorInternal.class, mDeviceStorageMonitorInternal);
+ when(mSpiedContext.getSystemService(StorageManager.class)).thenReturn(mStorageManager);
+ mockGetLocalService(LockSettingsInternal.class, mLockSettingsInternal);
+ mockGetLocalService(PackageManagerInternal.class, mPackageManagerInternal);
+ doNothing().when(mSpiedContext).sendBroadcastAsUser(any(), any(), any());
+
// Must construct UserManagerService in the UiThread
mUms = new UserManagerService(mSpiedContext, mMockPms, mMockUserDataPreparer,
mPackagesLock, mRealContext.getDataDir(), mUsers);
@@ -223,6 +242,87 @@
.that(mUms.isUserRunning(PROFILE_USER_ID)).isFalse();
}
+ @Test
+ public void testSetBootUser_SuppliedUserIsSwitchable() throws Exception {
+ addUser(USER_ID);
+ addUser(OTHER_USER_ID);
+
+ mUms.setBootUser(OTHER_USER_ID);
+
+ assertWithMessage("getBootUser")
+ .that(mUmi.getBootUser()).isEqualTo(OTHER_USER_ID);
+ }
+
+ @Test
+ public void testSetBootUser_NotHeadless_SuppliedUserIsNotSwitchable() throws Exception {
+ setSystemUserHeadless(false);
+ addUser(USER_ID);
+ addUser(OTHER_USER_ID);
+ addDefaultProfileAndParent();
+
+ mUms.setBootUser(PROFILE_USER_ID);
+
+ assertWithMessage("getBootUser")
+ .that(mUmi.getBootUser()).isEqualTo(UserHandle.USER_SYSTEM);
+ }
+
+ @Test
+ public void testSetBootUser_Headless_SuppliedUserIsNotSwitchable() throws Exception {
+ setSystemUserHeadless(true);
+ addUser(USER_ID);
+ setLastForegroundTime(USER_ID, 1_000_000L);
+ addUser(OTHER_USER_ID);
+ setLastForegroundTime(OTHER_USER_ID, 2_000_000L);
+ addDefaultProfileAndParent();
+
+ mUms.setBootUser(PROFILE_USER_ID);
+
+ // Boot user not switchable so return most recently in foreground.
+ assertWithMessage("getBootUser")
+ .that(mUmi.getBootUser()).isEqualTo(OTHER_USER_ID);
+ }
+
+ @Test
+ public void testGetBootUser_NotHeadless_ReturnsSystemUser() throws Exception {
+ setSystemUserHeadless(false);
+ addUser(USER_ID);
+ addUser(OTHER_USER_ID);
+
+ assertWithMessage("getBootUser")
+ .that(mUmi.getBootUser()).isEqualTo(UserHandle.USER_SYSTEM);
+ }
+
+ @Test
+ public void testGetBootUser_Headless_ReturnsMostRecentlyInForeground() throws Exception {
+ setSystemUserHeadless(true);
+ addUser(USER_ID);
+ setLastForegroundTime(USER_ID, 1_000_000L);
+
+ addUser(OTHER_USER_ID);
+ setLastForegroundTime(OTHER_USER_ID, 2_000_000L);
+
+ assertWithMessage("getBootUser")
+ .that(mUmi.getBootUser()).isEqualTo(OTHER_USER_ID);
+ }
+
+ @Test
+ public void testGetBootUser_Headless_UserCreatedIfOnlySystemUserExists() throws Exception {
+ setSystemUserHeadless(true);
+
+ int bootUser = mUmi.getBootUser();
+
+ assertWithMessage("getStartingUser")
+ .that(bootUser).isNotEqualTo(UserHandle.USER_SYSTEM);
+
+ UserData newUser = mUsers.get(bootUser);
+ assertWithMessage("New boot user is a full user")
+ .that(newUser.info.isFull()).isTrue();
+ assertWithMessage("New boot user is an admin user")
+ .that(newUser.info.isAdmin()).isTrue();
+ assertWithMessage("New boot user is the main user")
+ .that(newUser.info.isMain()).isTrue();
+ }
+
private void mockCurrentUser(@UserIdInt int userId) {
mockGetLocalService(ActivityManagerInternal.class, mActivityManagerInternal);
@@ -248,7 +348,7 @@
private void addUser(@UserIdInt int userId) {
TestUserData userData = new TestUserData(userId);
-
+ userData.info.flags = UserInfo.FLAG_FULL;
addUserData(userData);
}
@@ -277,6 +377,23 @@
mUsers.put(userData.info.id, userData);
}
+ private void setSystemUserHeadless(boolean headless) {
+ UserData systemUser = mUsers.get(UserHandle.USER_SYSTEM);
+ if (headless) {
+ systemUser.info.flags &= ~UserInfo.FLAG_FULL;
+ systemUser.info.userType = UserManager.USER_TYPE_SYSTEM_HEADLESS;
+ } else {
+ systemUser.info.flags |= UserInfo.FLAG_FULL;
+ systemUser.info.userType = UserManager.USER_TYPE_FULL_SYSTEM;
+ }
+ doReturn(headless).when(() -> UserManager.isHeadlessSystemUserMode());
+ }
+
+ private void setLastForegroundTime(@UserIdInt int userId, long timeMillis) {
+ UserData userData = mUsers.get(userId);
+ userData.mLastEnteredForegroundTimeMillis = timeMillis;
+ }
+
private static final class TestUserData extends UserData {
@SuppressWarnings("deprecation")
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorSUSDTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorSUSDTest.java
index 88709e1..b9ba780 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorSUSDTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorSUSDTest.java
@@ -49,6 +49,7 @@
int result = mMediator.assignUserToDisplayOnStart(USER_ID, USER_ID, FG,
DEFAULT_DISPLAY);
assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
+ expectUserCannotBeUnassignedFromDisplay(USER_ID, DEFAULT_DISPLAY);
expectUserIsVisible(USER_ID);
expectUserIsNotVisibleOnDisplay(USER_ID, INVALID_DISPLAY);
@@ -80,6 +81,7 @@
int result = mMediator.assignUserToDisplayOnStart(currentUserId, currentUserId, FG,
DEFAULT_DISPLAY);
assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
+ expectUserCannotBeUnassignedFromDisplay(currentUserId, DEFAULT_DISPLAY);
expectUserIsVisible(currentUserId);
expectUserIsNotVisibleOnDisplay(currentUserId, INVALID_DISPLAY);
@@ -110,6 +112,7 @@
int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
BG_VISIBLE, DEFAULT_DISPLAY);
assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
+ expectUserCannotBeUnassignedFromDisplay(PROFILE_USER_ID, DEFAULT_DISPLAY);
expectUserIsVisible(PROFILE_USER_ID);
expectUserIsNotVisibleOnDisplay(PROFILE_USER_ID, INVALID_DISPLAY);
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java
index e4664d2..c59834b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java
@@ -165,12 +165,16 @@
expectNoDisplayAssignedToUser(USER_ID);
expectInitialCurrentUserAssignedToDisplay(DEFAULT_DISPLAY);
+ assertInvisibleUserCannotBeAssignedExtraDisplay(USER_ID, SECONDARY_DISPLAY_ID);
+
listener.verify();
}
@Test
public final void testStartVisibleBgUser_onDefaultDisplay() throws Exception {
visibleBgUserCannotBeStartedOnDefaultDisplayTest();
+
+ assertInvisibleUserCannotBeAssignedExtraDisplay(USER_ID, SECONDARY_DISPLAY_ID);
}
protected final void visibleBgUserCannotBeStartedOnDefaultDisplayTest() throws Exception {
@@ -180,8 +184,8 @@
DEFAULT_DISPLAY);
assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
- expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
- expectNoDisplayAssignedToUser(PROFILE_USER_ID);
+ expectUserIsNotVisibleAtAll(USER_ID);
+ expectNoDisplayAssignedToUser(USER_ID);
listener.verify();
}
@@ -194,8 +198,11 @@
SECONDARY_DISPLAY_ID);
assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
- expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
- expectNoDisplayAssignedToUser(PROFILE_USER_ID);
+ expectUserIsNotVisibleAtAll(USER_ID);
+ expectNoDisplayAssignedToUser(USER_ID);
+
+ assertInvisibleUserCannotBeAssignedExtraDisplay(USER_ID, SECONDARY_DISPLAY_ID);
+ assertInvisibleUserCannotBeAssignedExtraDisplay(USER_ID, OTHER_SECONDARY_DISPLAY_ID);
listener.verify();
}
@@ -217,6 +224,9 @@
expectNoDisplayAssignedToUser(USER_SYSTEM);
expectUserAssignedToDisplay(SECONDARY_DISPLAY_ID, USER_ID);
+ assertUserCannotBeAssignedExtraDisplay(USER_SYSTEM, SECONDARY_DISPLAY_ID);
+ assertUserCannotBeAssignedExtraDisplay(USER_SYSTEM, OTHER_SECONDARY_DISPLAY_ID);
+
listener.verify();
}
@@ -256,6 +266,8 @@
expectNoDisplayAssignedToUser(PROFILE_USER_ID);
expectUserAssignedToDisplay(DEFAULT_DISPLAY, OTHER_USER_ID);
+ assertUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
+
listener.verify();
}
@@ -289,6 +301,8 @@
expectNoDisplayAssignedToUser(PROFILE_USER_ID);
expectInitialCurrentUserAssignedToDisplay(DEFAULT_DISPLAY);
+ assertUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
+
listener.verify();
}
@@ -305,6 +319,10 @@
expectNoDisplayAssignedToUser(PROFILE_USER_ID);
expectInitialCurrentUserAssignedToDisplay(SECONDARY_DISPLAY_ID);
+ assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
+ assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID,
+ OTHER_SECONDARY_DISPLAY_ID);
+
listener.verify();
}
@@ -320,6 +338,10 @@
expectNoDisplayAssignedToUser(PROFILE_USER_ID);
expectInitialCurrentUserAssignedToDisplay(SECONDARY_DISPLAY_ID);
+ assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
+ assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID,
+ OTHER_SECONDARY_DISPLAY_ID);
+
listener.verify();
}
@@ -336,6 +358,9 @@
expectNoDisplayAssignedToUser(PROFILE_USER_ID);
expectInitialCurrentUserAssignedToDisplay(DEFAULT_DISPLAY);
+ assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, DEFAULT_DISPLAY);
+ assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
+
listener.verify();
}
@@ -351,6 +376,10 @@
expectNoDisplayAssignedToUser(PROFILE_USER_ID);
expectInitialCurrentUserAssignedToDisplay(SECONDARY_DISPLAY_ID);
+ assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
+ assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID,
+ OTHER_SECONDARY_DISPLAY_ID);
+
listener.verify();
}
@@ -481,6 +510,63 @@
.that(actualResult).isEqualTo(expectedResult);
}
+ protected void assertBgUserBecomesInvisibleOnStop(@UserIdInt int userId) {
+ Log.d(TAG, "Stopping user " + userId);
+ mMediator.unassignUserFromDisplayOnStop(userId);
+ expectUserIsNotVisibleAtAll(userId);
+ }
+
+ /**
+ * Assigns and unassigns the user to / from an extra display, asserting the visibility state in
+ * between.
+ *
+ * <p>It assumes the user was not visible in the display beforehand.
+ */
+ protected void assertUserCanBeAssignedExtraDisplay(@UserIdInt int userId, int displayId) {
+ assertUserCanBeAssignedExtraDisplay(userId, displayId, /* unassign= */ true);
+ }
+
+ protected void assertUserCanBeAssignedExtraDisplay(@UserIdInt int userId, int displayId,
+ boolean unassign) {
+
+ expectUserIsNotVisibleOnDisplay(userId, displayId);
+
+ Log.d(TAG, "Calling assignUserToExtraDisplay(" + userId + ", " + displayId + ")");
+ assertWithMessage("assignUserToExtraDisplay(%s, %s)", userId, displayId)
+ .that(mMediator.assignUserToExtraDisplay(userId, displayId))
+ .isTrue();
+ expectUserIsVisibleOnDisplay(userId, displayId);
+
+ if (unassign) {
+ Log.d(TAG, "Calling unassignUserFromExtraDisplay(" + userId + ", " + displayId + ")");
+ assertWithMessage("unassignUserFromExtraDisplay(%s, %s)", userId, displayId)
+ .that(mMediator.unassignUserFromExtraDisplay(userId, displayId))
+ .isTrue();
+ expectUserIsNotVisibleOnDisplay(userId, displayId);
+ }
+ }
+
+ /**
+ * Asserts that a user (already visible or not) cannot be assigned to an extra display (and
+ * hence won't be visible on that display).
+ */
+ protected void assertUserCannotBeAssignedExtraDisplay(@UserIdInt int userId, int displayId) {
+ expectWithMessage("assignUserToExtraDisplay(%s, %s)", userId, displayId)
+ .that(mMediator.assignUserToExtraDisplay(userId, displayId))
+ .isFalse();
+ expectUserIsNotVisibleOnDisplay(userId, displayId);
+ }
+
+ /**
+ * Asserts that an invisible user cannot be assigned to an extra display.
+ */
+ protected void assertInvisibleUserCannotBeAssignedExtraDisplay(@UserIdInt int userId,
+ int displayId) {
+ assertUserCannotBeAssignedExtraDisplay(userId, displayId);
+ expectNoDisplayAssignedToUser(userId);
+ expectInitialCurrentUserAssignedToDisplay(displayId);
+ }
+
protected void expectUserIsVisible(@UserIdInt int userId) {
expectWithMessage("isUserVisible(%s)", userId)
.that(mMediator.isUserVisible(userId))
@@ -534,6 +620,11 @@
.that(mMediator.getDisplayAssignedToUser(userId)).isEqualTo(INVALID_DISPLAY);
}
+ protected void expectUserCannotBeUnassignedFromDisplay(@UserIdInt int userId, int displayId) {
+ expectWithMessage("unassignUserFromExtraDisplay(%s, %s)", userId, displayId)
+ .that(mMediator.unassignUserFromExtraDisplay(userId, displayId)).isFalse();
+ }
+
protected void expectUserAssignedToDisplay(int displayId, @UserIdInt int userId) {
expectWithMessage("getUserAssignedToDisplay(%s)", displayId)
.that(mMediator.getUserAssignedToDisplay(displayId)).isEqualTo(userId);
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorVisibleBackgroundUserTestCase.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorVisibleBackgroundUserTestCase.java
index 66d7eb6..627553b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorVisibleBackgroundUserTestCase.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorVisibleBackgroundUserTestCase.java
@@ -52,6 +52,7 @@
int result = mMediator.assignUserToDisplayOnStart(USER_ID, USER_ID, FG,
DEFAULT_DISPLAY);
assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
+ expectUserCannotBeUnassignedFromDisplay(USER_ID, DEFAULT_DISPLAY);
expectUserIsVisible(USER_ID);
expectUserIsVisibleOnDisplay(USER_ID, DEFAULT_DISPLAY);
@@ -64,7 +65,9 @@
expectUserAssignedToDisplay(INVALID_DISPLAY, USER_ID);
expectUserAssignedToDisplay(SECONDARY_DISPLAY_ID, USER_ID);
- expectDisplayAssignedToUser(USER_NULL, INVALID_DISPLAY);
+ expectNoDisplayAssignedToUser(USER_NULL);
+
+ assertUserCanBeAssignedExtraDisplay(USER_ID, SECONDARY_DISPLAY_ID);
listener.verify();
}
@@ -83,6 +86,7 @@
int result = mMediator.assignUserToDisplayOnStart(currentUserId, currentUserId, FG,
DEFAULT_DISPLAY);
assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
+ expectUserCannotBeUnassignedFromDisplay(currentUserId, DEFAULT_DISPLAY);
expectUserIsVisible(currentUserId);
expectUserIsVisibleOnDisplay(currentUserId, DEFAULT_DISPLAY);
@@ -98,6 +102,8 @@
expectUserIsNotVisibleAtAll(previousCurrentUserId);
expectNoDisplayAssignedToUser(previousCurrentUserId);
+ assertUserCanBeAssignedExtraDisplay(USER_ID, SECONDARY_DISPLAY_ID);
+
listener.verify();
}
@@ -113,6 +119,7 @@
int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
BG_VISIBLE, DEFAULT_DISPLAY);
assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
+ expectUserCannotBeUnassignedFromDisplay(PROFILE_USER_ID, DEFAULT_DISPLAY);
expectUserIsVisible(PROFILE_USER_ID);
expectUserIsNotVisibleOnDisplay(PROFILE_USER_ID, INVALID_DISPLAY);
@@ -123,6 +130,8 @@
expectDisplayAssignedToUser(PROFILE_USER_ID, DEFAULT_DISPLAY);
expectUserAssignedToDisplay(DEFAULT_DISPLAY, PARENT_USER_ID);
+ assertUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
+
listener.verify();
}
@@ -134,6 +143,9 @@
assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
+ assertInvisibleUserCannotBeAssignedExtraDisplay(USER_ID, DEFAULT_DISPLAY);
+ assertInvisibleUserCannotBeAssignedExtraDisplay(USER_ID, SECONDARY_DISPLAY_ID);
+
listener.verify();
}
@@ -148,6 +160,9 @@
expectUserIsNotVisibleAtAll(USER_ID);
+ assertInvisibleUserCannotBeAssignedExtraDisplay(USER_ID, DEFAULT_DISPLAY);
+ assertInvisibleUserCannotBeAssignedExtraDisplay(USER_ID, SECONDARY_DISPLAY_ID);
+
listener.verify();
}
@@ -159,6 +174,7 @@
int result = mMediator.assignUserToDisplayOnStart(USER_ID, USER_ID, BG_VISIBLE,
SECONDARY_DISPLAY_ID);
assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
+ expectUserCannotBeUnassignedFromDisplay(USER_ID, SECONDARY_DISPLAY_ID);
expectUserIsVisible(USER_ID);
expectUserIsVisibleOnDisplay(USER_ID, SECONDARY_DISPLAY_ID);
@@ -169,7 +185,16 @@
expectDisplayAssignedToUser(USER_ID, SECONDARY_DISPLAY_ID);
expectUserAssignedToDisplay(SECONDARY_DISPLAY_ID, USER_ID);
- listener.verify();
+ assertUserCanBeAssignedExtraDisplay(USER_ID, OTHER_SECONDARY_DISPLAY_ID);
+
+ // Assign again, without unassigning (to make sure it becomes invisible on stop)
+ AsyncUserVisibilityListener listener2 = addListenerForEvents(onInvisible(USER_ID));
+ assertUserCanBeAssignedExtraDisplay(USER_ID, OTHER_SECONDARY_DISPLAY_ID,
+ /* unassign= */ false);
+
+ assertBgUserBecomesInvisibleOnStop(USER_ID);
+
+ listener2.verify();
}
@Test
@@ -203,6 +228,8 @@
expectNoDisplayAssignedToUser(USER_ID);
expectUserAssignedToDisplay(SECONDARY_DISPLAY_ID, OTHER_USER_ID);
+ assertUserCannotBeAssignedExtraDisplay(USER_ID, SECONDARY_DISPLAY_ID);
+
listener.verify();
}
@@ -226,7 +253,18 @@
expectDisplayAssignedToUser(USER_ID, OTHER_SECONDARY_DISPLAY_ID);
expectUserAssignedToDisplay(OTHER_SECONDARY_DISPLAY_ID, USER_ID);
+ assertUserCanBeAssignedExtraDisplay(USER_ID, SECONDARY_DISPLAY_ID);
+
listener.verify();
+
+ // Assign again, without unassigning (to make sure it becomes invisible on stop)
+ AsyncUserVisibilityListener listener2 = addListenerForEvents(onInvisible(USER_ID));
+ assertUserCanBeAssignedExtraDisplay(USER_ID, SECONDARY_DISPLAY_ID,
+ /* unassign= */ false);
+
+ assertBgUserBecomesInvisibleOnStop(USER_ID);
+
+ listener2.verify();
}
@Test
@@ -244,12 +282,14 @@
expectNoDisplayAssignedToUser(PROFILE_USER_ID);
expectUserAssignedToDisplay(OTHER_SECONDARY_DISPLAY_ID, PARENT_USER_ID);
+ assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
+
listener.verify();
}
+ // Conditions below are asserted on other tests, but they're explicitly checked in the 2
+ // tests below (which call this method) as well
private void currentUserVisibilityWhenNoDisplayIsAssignedTest(@UserIdInt int currentUserId) {
- // Conditions below are asserted on other tests, but they're explicitly checked in the 2
- // tests below as well
expectUserIsVisible(currentUserId);
expectUserIsVisibleOnDisplay(currentUserId, DEFAULT_DISPLAY);
expectUserIsNotVisibleOnDisplay(currentUserId, SECONDARY_DISPLAY_ID);
@@ -277,4 +317,13 @@
expectUserIsNotVisibleAtAll(INITIAL_CURRENT_USER_ID);
expectDisplayAssignedToUser(INITIAL_CURRENT_USER_ID, INVALID_DISPLAY);
}
+
+ @Test
+ public final void testAssignUserToExtraDisplay_invalidDisplays() throws Exception {
+ expectWithMessage("assignUserToExtraDisplay(%s, %s)", USER_ID, INVALID_DISPLAY)
+ .that(mMediator.assignUserToExtraDisplay(USER_ID, INVALID_DISPLAY)).isFalse();
+ // DEFAULT_DISPLAY is always assigned to the current user
+ expectWithMessage("assignUserToExtraDisplay(%s, %s)", USER_ID, DEFAULT_DISPLAY)
+ .that(mMediator.assignUserToExtraDisplay(USER_ID, DEFAULT_DISPLAY)).isFalse();
+ }
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java b/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java
index bcba4a1..c08f6bf 100644
--- a/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java
@@ -28,7 +28,7 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
-import static com.android.server.wallpaper.WallpaperManagerService.WALLPAPER;
+import static com.android.server.wallpaper.WallpaperUtils.WALLPAPER;
import static org.hamcrest.core.IsNot.not;
import static org.junit.Assert.assertEquals;
@@ -71,7 +71,6 @@
import android.util.Xml;
import android.view.Display;
-import androidx.test.filters.FlakyTest;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
@@ -89,6 +88,7 @@
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.ClassRule;
+import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
@@ -110,7 +110,6 @@
* atest FrameworksMockingServicesTests:WallpaperManagerServiceTests
*/
@Presubmit
-@FlakyTest(bugId = 129797242)
@RunWith(AndroidJUnit4.class)
public class WallpaperManagerServiceTests {
@@ -273,8 +272,10 @@
/**
* Tests setWallpaperComponent and clearWallpaper should work as expected.
+ * TODO ignored since the assumption never passes. to be investigated.
*/
@Test
+ @Ignore("b/264533465")
public void testSetThenClearComponent() {
// Skip if there is no pre-defined default wallpaper component.
assumeThat(sDefaultWallpaperComponent,
@@ -285,7 +286,7 @@
verifyLastWallpaperData(testUserId, sDefaultWallpaperComponent);
verifyCurrentSystemData(testUserId);
- mService.setWallpaperComponent(sImageWallpaperComponentName);
+ mService.setWallpaperComponent(sImageWallpaperComponentName, FLAG_SYSTEM, testUserId);
verifyLastWallpaperData(testUserId, sImageWallpaperComponentName);
verifyCurrentSystemData(testUserId);
@@ -312,7 +313,7 @@
WallpaperManagerService.WallpaperConnection.DisplayConnector connector =
mService.mLastWallpaper.connection.getDisplayConnectorOrCreate(DEFAULT_DISPLAY);
- mService.setWallpaperComponent(sDefaultWallpaperComponent);
+ mService.setWallpaperComponent(sDefaultWallpaperComponent, FLAG_SYSTEM, testUserId);
verify(connector.mEngine).dispatchWallpaperCommand(
eq(COMMAND_REAPPLY), anyInt(), anyInt(), anyInt(), any());
@@ -454,7 +455,7 @@
public void testGetAdjustedWallpaperColorsOnDimming() throws RemoteException {
final int testUserId = USER_SYSTEM;
mService.switchUser(testUserId, null);
- mService.setWallpaperComponent(sDefaultWallpaperComponent);
+ mService.setWallpaperComponent(sDefaultWallpaperComponent, FLAG_SYSTEM, testUserId);
WallpaperData wallpaper = mService.getCurrentWallpaperData(FLAG_SYSTEM, testUserId);
// Mock a wallpaper data with color hints that support dark text and dark theme
diff --git a/services/tests/servicestests/res/raw/dummy_keyboard_layout.kcm b/services/tests/servicestests/res/raw/dummy_keyboard_layout.kcm
new file mode 100644
index 0000000..ea6bc98
--- /dev/null
+++ b/services/tests/servicestests/res/raw/dummy_keyboard_layout.kcm
@@ -0,0 +1,311 @@
+# Copyright (C) 2023 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# English (US) keyboard layout.
+# Unlike the default (generic) keyboard layout, English (US) does not contain any
+# special ALT characters.
+#
+
+type OVERLAY
+
+### ROW 1
+
+key GRAVE {
+ label: '`'
+ base: '`'
+ shift: '~'
+}
+
+key 1 {
+ label: '1'
+ base: '1'
+ shift: '!'
+}
+
+key 2 {
+ label: '2'
+ base: '2'
+ shift: '@'
+}
+
+key 3 {
+ label: '3'
+ base: '3'
+ shift: '#'
+}
+
+key 4 {
+ label: '4'
+ base: '4'
+ shift: '$'
+}
+
+key 5 {
+ label: '5'
+ base: '5'
+ shift: '%'
+}
+
+key 6 {
+ label: '6'
+ base: '6'
+ shift: '^'
+}
+
+key 7 {
+ label: '7'
+ base: '7'
+ shift: '&'
+}
+
+key 8 {
+ label: '8'
+ base: '8'
+ shift: '*'
+}
+
+key 9 {
+ label: '9'
+ base: '9'
+ shift: '('
+}
+
+key 0 {
+ label: '0'
+ base: '0'
+ shift: ')'
+}
+
+key MINUS {
+ label: '-'
+ base: '-'
+ shift: '_'
+}
+
+key EQUALS {
+ label: '='
+ base: '='
+ shift: '+'
+}
+
+### ROW 2
+
+key Q {
+ label: 'Q'
+ base: 'q'
+ shift, capslock: 'Q'
+}
+
+key W {
+ label: 'W'
+ base: 'w'
+ shift, capslock: 'W'
+}
+
+key E {
+ label: 'E'
+ base: 'e'
+ shift, capslock: 'E'
+}
+
+key R {
+ label: 'R'
+ base: 'r'
+ shift, capslock: 'R'
+}
+
+key T {
+ label: 'T'
+ base: 't'
+ shift, capslock: 'T'
+}
+
+key Y {
+ label: 'Y'
+ base: 'y'
+ shift, capslock: 'Y'
+}
+
+key U {
+ label: 'U'
+ base: 'u'
+ shift, capslock: 'U'
+}
+
+key I {
+ label: 'I'
+ base: 'i'
+ shift, capslock: 'I'
+}
+
+key O {
+ label: 'O'
+ base: 'o'
+ shift, capslock: 'O'
+}
+
+key P {
+ label: 'P'
+ base: 'p'
+ shift, capslock: 'P'
+}
+
+key LEFT_BRACKET {
+ label: '['
+ base: '['
+ shift: '{'
+}
+
+key RIGHT_BRACKET {
+ label: ']'
+ base: ']'
+ shift: '}'
+}
+
+key BACKSLASH {
+ label: '\\'
+ base: '\\'
+ shift: '|'
+}
+
+### ROW 3
+
+key A {
+ label: 'A'
+ base: 'a'
+ shift, capslock: 'A'
+}
+
+key S {
+ label: 'S'
+ base: 's'
+ shift, capslock: 'S'
+}
+
+key D {
+ label: 'D'
+ base: 'd'
+ shift, capslock: 'D'
+}
+
+key F {
+ label: 'F'
+ base: 'f'
+ shift, capslock: 'F'
+}
+
+key G {
+ label: 'G'
+ base: 'g'
+ shift, capslock: 'G'
+}
+
+key H {
+ label: 'H'
+ base: 'h'
+ shift, capslock: 'H'
+}
+
+key J {
+ label: 'J'
+ base: 'j'
+ shift, capslock: 'J'
+}
+
+key K {
+ label: 'K'
+ base: 'k'
+ shift, capslock: 'K'
+}
+
+key L {
+ label: 'L'
+ base: 'l'
+ shift, capslock: 'L'
+}
+
+key SEMICOLON {
+ label: ';'
+ base: ';'
+ shift: ':'
+}
+
+key APOSTROPHE {
+ label: '\''
+ base: '\''
+ shift: '"'
+}
+
+### ROW 4
+
+key Z {
+ label: 'Z'
+ base: 'z'
+ shift, capslock: 'Z'
+}
+
+key X {
+ label: 'X'
+ base: 'x'
+ shift, capslock: 'X'
+}
+
+key C {
+ label: 'C'
+ base: 'c'
+ shift, capslock: 'C'
+}
+
+key V {
+ label: 'V'
+ base: 'v'
+ shift, capslock: 'V'
+}
+
+key B {
+ label: 'B'
+ base: 'b'
+ shift, capslock: 'B'
+}
+
+key N {
+ label: 'N'
+ base: 'n'
+ shift, capslock: 'N'
+}
+
+key M {
+ label: 'M'
+ base: 'm'
+ shift, capslock: 'M'
+}
+
+key COMMA {
+ label: ','
+ base: ','
+ shift: '<'
+}
+
+key PERIOD {
+ label: '.'
+ base: '.'
+ shift: '>'
+}
+
+key SLASH {
+ label: '/'
+ base: '/'
+ shift: '?'
+}
diff --git a/services/tests/servicestests/res/xml/keyboard_layouts.xml b/services/tests/servicestests/res/xml/keyboard_layouts.xml
new file mode 100644
index 0000000..b5a05fc
--- /dev/null
+++ b/services/tests/servicestests/res/xml/keyboard_layouts.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<keyboard-layouts xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+ <keyboard-layout
+ android:name="keyboard_layout_english_uk"
+ android:label="English (UK)"
+ android:keyboardLayout="@raw/dummy_keyboard_layout"
+ android:keyboardLocale="en-Latn-GB"
+ android:keyboardLayoutType="qwerty" />
+
+ <keyboard-layout
+ android:name="keyboard_layout_english_us"
+ android:label="English (US)"
+ android:keyboardLayout="@raw/dummy_keyboard_layout"
+ android:keyboardLocale="en-Latn,en-Latn-US"
+ android:keyboardLayoutType="qwerty" />
+
+ <keyboard-layout
+ android:name="keyboard_layout_english_us_intl"
+ android:label="English (International)"
+ android:keyboardLayout="@raw/dummy_keyboard_layout"
+ android:keyboardLocale="en-Latn-US"
+ android:keyboardLayoutType="extended" />
+
+ <keyboard-layout
+ android:name="keyboard_layout_english_us_dvorak"
+ android:label="English (Dvorak)"
+ android:keyboardLayout="@raw/dummy_keyboard_layout"
+ android:keyboardLocale="en-Latn-US"
+ android:keyboardLayoutType="dvorak" />
+
+ <keyboard-layout
+ android:name="keyboard_layout_german"
+ android:label="German"
+ android:keyboardLayout="@raw/dummy_keyboard_layout"
+ android:keyboardLocale="de-Latn"
+ android:keyboardLayoutType="qwertz" />
+
+ <keyboard-layout
+ android:name="keyboard_layout_french"
+ android:label="French"
+ android:keyboardLayout="@raw/dummy_keyboard_layout"
+ android:keyboardLocale="fr-Latn-FR"
+ android:keyboardLayoutType="azerty" />
+
+ <keyboard-layout
+ android:name="keyboard_layout_russian_qwerty"
+ android:label="Russian"
+ android:keyboardLayout="@raw/dummy_keyboard_layout"
+ android:keyboardLocale="ru-Cyrl"
+ android:keyboardLayoutType="qwerty" />
+
+ <keyboard-layout
+ android:name="keyboard_layout_russian"
+ android:label="Russian"
+ android:keyboardLayout="@raw/dummy_keyboard_layout"
+ android:keyboardLocale="ru-Cyrl" />
+
+ <keyboard-layout
+ android:name="keyboard_layout_vendorId:1,productId:1"
+ android:label="vendorId:1,productId:1"
+ android:keyboardLayout="@raw/dummy_keyboard_layout"
+ androidprv:vendorId="1"
+ androidprv:productId="1" />
+</keyboard-layouts>
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
index d056348..448ffe5 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
@@ -55,6 +55,7 @@
import android.hardware.display.DisplayManagerGlobal;
import android.os.Bundle;
import android.os.IBinder;
+import android.os.LocaleList;
import android.os.UserHandle;
import android.provider.Settings;
import android.testing.TestableContext;
@@ -106,7 +107,8 @@
private static final String INTENT_ACTION = "TESTACTION";
private static final String DESCRIPTION = "description";
private static final PendingIntent TEST_PENDING_INTENT = PendingIntent.getBroadcast(
- ApplicationProvider.getApplicationContext(), 0, new Intent(INTENT_ACTION),
+ ApplicationProvider.getApplicationContext(), 0, new Intent(INTENT_ACTION)
+ .setPackage(ApplicationProvider.getApplicationContext().getPackageName()),
PendingIntent.FLAG_MUTABLE_UNAUDITED);
private static final RemoteAction TEST_ACTION = new RemoteAction(
Icon.createWithContentUri("content://test"),
@@ -487,7 +489,7 @@
final int userid = 10;
final int windowId = 100;
final AccessibilityWindowAttributes attributes = new AccessibilityWindowAttributes(
- new WindowManager.LayoutParams());
+ new WindowManager.LayoutParams(), LocaleList.getEmptyLocaleList());
mA11yms.setAccessibilityWindowAttributes(displayId, windowId, userid, attributes);
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java
index 7b7e1e0..2dfabd0 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java
@@ -43,6 +43,7 @@
import android.graphics.Region;
import android.os.IBinder;
+import android.os.LocaleList;
import android.os.RemoteException;
import android.os.UserHandle;
import android.text.TextUtils;
@@ -909,7 +910,7 @@
final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
layoutParams.accessibilityTitle = "accessibility window title";
final AccessibilityWindowAttributes attributes = new AccessibilityWindowAttributes(
- layoutParams);
+ layoutParams, new LocaleList());
mA11yWindowManager.setAccessibilityWindowAttributes(Display.DEFAULT_DISPLAY, windowId,
USER_SYSTEM_ID, attributes);
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/SystemActionPerformerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/SystemActionPerformerTest.java
index bbcf77b..13d93cb 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/SystemActionPerformerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/SystemActionPerformerTest.java
@@ -76,14 +76,18 @@
private static final String DESCRIPTION1 = "description1";
private static final String DESCRIPTION2 = "description2";
private static final PendingIntent TEST_PENDING_INTENT_1 = PendingIntent.getBroadcast(
- InstrumentationRegistry.getTargetContext(), 0, new Intent(INTENT_ACTION1), PendingIntent.FLAG_MUTABLE_UNAUDITED);
+ InstrumentationRegistry.getTargetContext(), 0, new Intent(INTENT_ACTION1)
+ .setPackage(InstrumentationRegistry.getTargetContext().getPackageName()),
+ PendingIntent.FLAG_MUTABLE_UNAUDITED);
private static final RemoteAction NEW_TEST_ACTION_1 = new RemoteAction(
Icon.createWithContentUri("content://test"),
LABEL_1,
DESCRIPTION1,
TEST_PENDING_INTENT_1);
private static final PendingIntent TEST_PENDING_INTENT_2 = PendingIntent.getBroadcast(
- InstrumentationRegistry.getTargetContext(), 0, new Intent(INTENT_ACTION2), PendingIntent.FLAG_MUTABLE_UNAUDITED);
+ InstrumentationRegistry.getTargetContext(), 0, new Intent(INTENT_ACTION2)
+ .setPackage(InstrumentationRegistry.getTargetContext().getPackageName()),
+ PendingIntent.FLAG_MUTABLE_UNAUDITED);
private static final RemoteAction NEW_TEST_ACTION_2 = new RemoteAction(
Icon.createWithContentUri("content://test"),
LABEL_2,
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
index 0780d21..d996e37 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
@@ -214,7 +214,8 @@
}
private void notRegistered_publicMethodsShouldBeBenign(int displayId) {
- assertFalse(mFullScreenMagnificationController.isMagnifying(displayId));
+ checkActivatedAndMagnifyingState(/* activated= */false, /* magnifying= */false, displayId);
+
assertFalse(
mFullScreenMagnificationController.magnificationRegionContains(displayId, 100,
100));
@@ -646,9 +647,9 @@
.setScale(displayId, 1.5f, startCenter.x, startCenter.y, false,
SERVICE_ID_2);
assertFalse(mFullScreenMagnificationController.resetIfNeeded(displayId, SERVICE_ID_1));
- assertTrue(mFullScreenMagnificationController.isMagnifying(displayId));
+ checkActivatedAndMagnifyingState(/* activated= */true, /* magnifying= */true, displayId);
assertTrue(mFullScreenMagnificationController.resetIfNeeded(displayId, SERVICE_ID_2));
- assertFalse(mFullScreenMagnificationController.isMagnifying(displayId));
+ checkActivatedAndMagnifyingState(/* activated= */false, /* magnifying= */false, displayId);
}
@Test
@@ -667,7 +668,7 @@
assertTrue(mFullScreenMagnificationController.resetIfNeeded(displayId, false));
verify(mRequestObserver).onFullScreenMagnificationChanged(eq(displayId),
eq(INITIAL_MAGNIFICATION_REGION), any(MagnificationConfig.class));
- assertFalse(mFullScreenMagnificationController.isMagnifying(displayId));
+ checkActivatedAndMagnifyingState(/* activated= */false, /* magnifying= */false, displayId);
assertFalse(mFullScreenMagnificationController.resetIfNeeded(displayId, false));
}
@@ -731,7 +732,7 @@
mTargetAnimationListener.onAnimationUpdate(mMockValueAnimator);
mStateListener.onAnimationEnd(mMockValueAnimator);
- assertFalse(mFullScreenMagnificationController.isMagnifying(DISPLAY_0));
+ checkActivatedAndMagnifyingState(/* activated= */false, /* magnifying= */false, displayId);
verify(lastAnimationCallback).onResult(true);
}
@@ -749,8 +750,8 @@
mMessageCapturingHandler.sendAllMessages();
br.onReceive(mMockContext, null);
mMessageCapturingHandler.sendAllMessages();
- assertFalse(mFullScreenMagnificationController.isMagnifying(DISPLAY_0));
- assertFalse(mFullScreenMagnificationController.isMagnifying(DISPLAY_1));
+ checkActivatedAndMagnifyingState(/* activated= */false, /* magnifying= */false, DISPLAY_0);
+ checkActivatedAndMagnifyingState(/* activated= */false, /* magnifying= */false, DISPLAY_1);
}
@Test
@@ -768,7 +769,7 @@
mMessageCapturingHandler.sendAllMessages();
callbacks.onUserContextChanged();
mMessageCapturingHandler.sendAllMessages();
- assertFalse(mFullScreenMagnificationController.isMagnifying(displayId));
+ checkActivatedAndMagnifyingState(/* activated= */false, /* magnifying= */false, displayId);
}
@Test
@@ -784,10 +785,10 @@
MagnificationCallbacks callbacks = getMagnificationCallbacks(displayId);
zoomIn2xToMiddle(displayId);
mMessageCapturingHandler.sendAllMessages();
- assertTrue(mFullScreenMagnificationController.isMagnifying(displayId));
+ checkActivatedAndMagnifyingState(/* activated= */true, /* magnifying= */true, displayId);
callbacks.onDisplaySizeChanged();
mMessageCapturingHandler.sendAllMessages();
- assertFalse(mFullScreenMagnificationController.isMagnifying(displayId));
+ checkActivatedAndMagnifyingState(/* activated= */false, /* magnifying= */false, DISPLAY_0);
}
@Test
@@ -1133,23 +1134,17 @@
}
@Test
- public void testSetForceShowMagnifiableBounds() {
+ public void testZoomTo1x_shouldActivatedAndForceShowMagnifiableBounds() {
register(DISPLAY_0);
+ final float scale = 1.0f;
+ mFullScreenMagnificationController.setScaleAndCenter(
+ DISPLAY_0, scale, Float.NaN, Float.NaN, true, SERVICE_ID_1);
- mFullScreenMagnificationController.setForceShowMagnifiableBounds(DISPLAY_0, true);
-
+ checkActivatedAndMagnifyingState(/* activated= */true, /* magnifying= */false, DISPLAY_0);
verify(mMockWindowManager).setForceShowMagnifiableBounds(DISPLAY_0, true);
}
@Test
- public void testIsForceShowMagnifiableBounds() {
- register(DISPLAY_0);
- mFullScreenMagnificationController.setForceShowMagnifiableBounds(DISPLAY_0, true);
-
- assertTrue(mFullScreenMagnificationController.isForceShowMagnifiableBounds(DISPLAY_0));
- }
-
- @Test
public void testSetScale_toMagnifying_shouldNotifyActivatedState() {
setScaleToMagnifying();
@@ -1220,7 +1215,15 @@
float scale = 2.0f;
mFullScreenMagnificationController.setScale(displayId, scale, startCenter.x, startCenter.y,
false, SERVICE_ID_1);
- assertTrue(mFullScreenMagnificationController.isMagnifying(displayId));
+ checkActivatedAndMagnifyingState(/* activated= */true, /* magnifying= */true, displayId);
+ }
+
+ private void checkActivatedAndMagnifyingState(
+ boolean activated, boolean magnifying, int displayId) {
+ final boolean isActivated = mFullScreenMagnificationController.isActivated(displayId);
+ final boolean isMagnifying = mFullScreenMagnificationController.getScale(displayId) > 1.0f;
+ assertTrue(isActivated == activated);
+ assertTrue(isMagnifying == magnifying);
}
private MagnificationCallbacks getMagnificationCallbacks(int displayId) {
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
index 0fed89b..5334e4c 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
@@ -19,6 +19,7 @@
import static android.view.MotionEvent.ACTION_DOWN;
import static android.view.MotionEvent.ACTION_MOVE;
import static android.view.MotionEvent.ACTION_POINTER_DOWN;
+import static android.view.MotionEvent.ACTION_POINTER_INDEX_SHIFT;
import static android.view.MotionEvent.ACTION_POINTER_UP;
import static android.view.MotionEvent.ACTION_UP;
@@ -78,24 +79,25 @@
* {@code
* digraph {
* IDLE -> SHORTCUT_TRIGGERED [label="a11y\nbtn"]
- * SHORTCUT_TRIGGERED -> IDLE [label="a11y\nbtn"]
* IDLE -> DOUBLE_TAP [label="2tap"]
* DOUBLE_TAP -> IDLE [label="timeout"]
- * DOUBLE_TAP -> TRIPLE_TAP_AND_HOLD [label="down"]
- * SHORTCUT_TRIGGERED -> TRIPLE_TAP_AND_HOLD [label="down"]
- * TRIPLE_TAP_AND_HOLD -> ZOOMED [label="up"]
- * TRIPLE_TAP_AND_HOLD -> DRAGGING_TMP [label="hold/\nswipe"]
- * DRAGGING_TMP -> IDLE [label="release"]
+ * DOUBLE_TAP -> ZOOMED [label="tap"]
+ * DOUBLE_TAP -> NON_ACTIVATED_ZOOMED_TMP [label="hold"]
+ * NON_ACTIVATED_ZOOMED_TMP -> IDLE [label="release"]
+ * SHORTCUT_TRIGGERED -> IDLE [label="a11y\nbtn"]
+ * SHORTCUT_TRIGGERED -> ZOOMED[label="tap"]
+ * SHORTCUT_TRIGGERED -> ACTIVATED_ZOOMED_TMP [label="hold"]
+ * SHORTCUT_TRIGGERED -> PANNING [label="2hold]
* ZOOMED -> ZOOMED_DOUBLE_TAP [label="2tap"]
- * ZOOMED_DOUBLE_TAP -> ZOOMED [label="timeout"]
- * ZOOMED_DOUBLE_TAP -> DRAGGING [label="hold"]
- * ZOOMED_DOUBLE_TAP -> IDLE [label="tap"]
- * DRAGGING -> ZOOMED [label="release"]
* ZOOMED -> IDLE [label="a11y\nbtn"]
* ZOOMED -> PANNING [label="2hold"]
+ * ZOOMED_DOUBLE_TAP -> ZOOMED [label="timeout"]
+ * ZOOMED_DOUBLE_TAP -> ACTIVATED_ZOOMED_TMP [label="hold"]
+ * ZOOMED_DOUBLE_TAP -> IDLE [label="tap"]
+ * ACTIVATED_ZOOMED_TMP -> ZOOMED [label="release"]
+ * PANNING -> ZOOMED [label="release"]
* PANNING -> PANNING_SCALING [label="pinch"]
* PANNING_SCALING -> ZOOMED [label="release"]
- * PANNING -> ZOOMED [label="release"]
* }
* }
*/
@@ -107,12 +109,11 @@
public static final int STATE_2TAPS = 3;
public static final int STATE_ZOOMED_2TAPS = 4;
public static final int STATE_SHORTCUT_TRIGGERED = 5;
- public static final int STATE_DRAGGING_TMP = 6;
- public static final int STATE_DRAGGING = 7;
+ public static final int STATE_NON_ACTIVATED_ZOOMED_TMP = 6;
+ public static final int STATE_ACTIVATED_ZOOMED_TMP = 7;
public static final int STATE_PANNING = 8;
public static final int STATE_SCALING_AND_PANNING = 9;
-
public static final int FIRST_STATE = STATE_IDLE;
public static final int LAST_STATE = STATE_SCALING_AND_PANNING;
@@ -164,10 +165,6 @@
public boolean magnificationRegionContains(int displayId, float x, float y) {
return true;
}
-
- @Override
- void setForceShowMagnifiableBounds(int displayId, boolean show) {
- }
};
mFullScreenMagnificationController.register(DISPLAY_0);
mClock = new OffsettableClock.Stopped();
@@ -266,11 +263,11 @@
@SuppressWarnings("Convert2MethodRef")
@Test
public void testAlternativeTransitions_areWorking() {
- // A11y button followed by a tap&hold turns temporary "viewport dragging" zoom on
+ // A11y button followed by a tap&hold turns temporary "viewport dragging" zoom in
assertTransition(STATE_SHORTCUT_TRIGGERED, () -> {
send(downEvent());
fastForward1sec();
- }, STATE_DRAGGING_TMP);
+ }, STATE_ACTIVATED_ZOOMED_TMP);
// A11y button followed by a tap turns zoom on
assertTransition(STATE_SHORTCUT_TRIGGERED, () -> tap(), STATE_ZOOMED);
@@ -281,7 +278,6 @@
// A11y button turns zoom off
assertTransition(STATE_ZOOMED, () -> triggerShortcut(), STATE_IDLE);
-
// Double tap times out while zoomed
assertTransition(STATE_ZOOMED_2TAPS, () -> {
allowEventDelegation();
@@ -291,8 +287,11 @@
// tap+tap+swipe doesn't get delegated
assertTransition(STATE_2TAPS, () -> swipe(), STATE_IDLE);
- // tap+tap+swipe initiates viewport dragging immediately
- assertTransition(STATE_2TAPS, () -> swipeAndHold(), STATE_DRAGGING_TMP);
+ // tap+tap+swipe&hold initiates temporary viewport dragging zoom in immediately
+ assertTransition(STATE_2TAPS, () -> swipeAndHold(), STATE_NON_ACTIVATED_ZOOMED_TMP);
+
+ // release when activated temporary zoom in back to zoomed
+ assertTransition(STATE_ACTIVATED_ZOOMED_TMP, () -> upEvent(), STATE_ZOOMED);
}
@Test
@@ -337,8 +336,10 @@
@Test
public void testTripleTapAndHold_zoomsImmediately() {
- assertZoomsImmediatelyOnSwipeFrom(STATE_2TAPS);
- assertZoomsImmediatelyOnSwipeFrom(STATE_SHORTCUT_TRIGGERED);
+ assertZoomsImmediatelyOnSwipeFrom(STATE_2TAPS, STATE_NON_ACTIVATED_ZOOMED_TMP);
+ assertZoomsImmediatelyOnSwipeFrom(STATE_SHORTCUT_TRIGGERED, STATE_ACTIVATED_ZOOMED_TMP);
+ assertZoomsImmediatelyOnSwipeFrom(STATE_ZOOMED_2TAPS, STATE_ACTIVATED_ZOOMED_TMP);
+
}
@Test
@@ -391,10 +392,10 @@
PointF pointer3 = new PointF(DEFAULT_X * 2, DEFAULT_Y);
send(downEvent());
- send(pointerEvent(ACTION_POINTER_DOWN, new PointF[] {pointer1, pointer2}));
- send(pointerEvent(ACTION_POINTER_DOWN, new PointF[] {pointer1, pointer2, pointer3}));
- send(pointerEvent(ACTION_POINTER_UP, new PointF[] {pointer1, pointer2, pointer3}));
- send(pointerEvent(ACTION_POINTER_UP, new PointF[] {pointer1, pointer2, pointer3}));
+ send(pointerEvent(ACTION_POINTER_DOWN, new PointF[] {pointer1, pointer2}, 1));
+ send(pointerEvent(ACTION_POINTER_DOWN, new PointF[] {pointer1, pointer2, pointer3}, 2));
+ send(pointerEvent(ACTION_POINTER_UP, new PointF[] {pointer1, pointer2, pointer3}, 2));
+ send(pointerEvent(ACTION_POINTER_UP, new PointF[] {pointer1, pointer2, pointer3}, 2));
send(upEvent());
assertIn(STATE_ZOOMED);
@@ -411,38 +412,53 @@
}
@Test
- public void testFirstFingerSwipe_TwoPinterDownAndZoomedState_panningState() {
+ public void testFirstFingerSwipe_twoPointerDownAndZoomedState_panningState() {
goFromStateIdleTo(STATE_ZOOMED);
PointF pointer1 = DEFAULT_POINT;
PointF pointer2 = new PointF(DEFAULT_X * 1.5f, DEFAULT_Y);
send(downEvent());
- send(pointerEvent(ACTION_POINTER_DOWN, new PointF[] {pointer1, pointer2}));
+ send(pointerEvent(ACTION_POINTER_DOWN, new PointF[] {pointer1, pointer2}, 1));
//The minimum movement to transit to panningState.
final float sWipeMinDistance = ViewConfiguration.get(mContext).getScaledTouchSlop();
pointer1.offset(sWipeMinDistance + 1, 0);
- send(pointerEvent(ACTION_MOVE, new PointF[] {pointer1, pointer2}));
+ send(pointerEvent(ACTION_MOVE, new PointF[] {pointer1, pointer2}, 0));
assertIn(STATE_PANNING);
- assertIn(STATE_PANNING);
returnToNormalFrom(STATE_PANNING);
}
@Test
- public void testSecondFingerSwipe_TwoPinterDownAndZoomedState_panningState() {
+ public void testSecondFingerSwipe_twoPointerDownAndZoomedState_panningState() {
goFromStateIdleTo(STATE_ZOOMED);
PointF pointer1 = DEFAULT_POINT;
PointF pointer2 = new PointF(DEFAULT_X * 1.5f, DEFAULT_Y);
send(downEvent());
- send(pointerEvent(ACTION_POINTER_DOWN, new PointF[] {pointer1, pointer2}));
+ send(pointerEvent(ACTION_POINTER_DOWN, new PointF[] {pointer1, pointer2}, 1));
//The minimum movement to transit to panningState.
final float sWipeMinDistance = ViewConfiguration.get(mContext).getScaledTouchSlop();
pointer2.offset(sWipeMinDistance + 1, 0);
- send(pointerEvent(ACTION_MOVE, new PointF[] {pointer1, pointer2}));
+ send(pointerEvent(ACTION_MOVE, new PointF[] {pointer1, pointer2}, 1));
assertIn(STATE_PANNING);
+ returnToNormalFrom(STATE_PANNING);
+ }
+
+ @Test
+ public void testSecondFingerSwipe_twoPointerDownAndShortcutTriggeredState_panningState() {
+ goFromStateIdleTo(STATE_SHORTCUT_TRIGGERED);
+ PointF pointer1 = DEFAULT_POINT;
+ PointF pointer2 = new PointF(DEFAULT_X * 1.5f, DEFAULT_Y);
+
+ send(downEvent());
+ send(pointerEvent(ACTION_POINTER_DOWN, new PointF[] {pointer1, pointer2}, 1));
+ //The minimum movement to transit to panningState.
+ final float sWipeMinDistance = ViewConfiguration.get(mContext).getScaledTouchSlop();
+ pointer2.offset(sWipeMinDistance + 1, 0);
+ send(pointerEvent(ACTION_MOVE, new PointF[] {pointer1, pointer2}, 1));
assertIn(STATE_PANNING);
+
returnToNormalFrom(STATE_PANNING);
}
@@ -474,11 +490,11 @@
}
}
- private void assertZoomsImmediatelyOnSwipeFrom(int state) {
- goFromStateIdleTo(state);
+ private void assertZoomsImmediatelyOnSwipeFrom(int fromState, int toState) {
+ goFromStateIdleTo(fromState);
swipeAndHold();
- assertIn(STATE_DRAGGING_TMP);
- returnToNormalFrom(STATE_DRAGGING_TMP);
+ assertIn(toState);
+ returnToNormalFrom(toState);
}
private void assertTransition(int fromState, Runnable transitionAction, int toState) {
@@ -522,44 +538,51 @@
case STATE_IDLE: {
check(tapCount() < 2, state);
check(!mMgh.mDetectingState.mShortcutTriggered, state);
+ check(!isActivated(), state);
check(!isZoomed(), state);
} break;
case STATE_ZOOMED: {
+ check(isActivated(), state);
check(isZoomed(), state);
check(tapCount() < 2, state);
} break;
case STATE_2TAPS: {
+ check(!isActivated(), state);
check(!isZoomed(), state);
check(tapCount() == 2, state);
} break;
case STATE_ZOOMED_2TAPS: {
+ check(isActivated(), state);
check(isZoomed(), state);
check(tapCount() == 2, state);
} break;
- case STATE_DRAGGING: {
+ case STATE_NON_ACTIVATED_ZOOMED_TMP: {
+ check(isActivated(), state);
check(isZoomed(), state);
check(mMgh.mCurrentState == mMgh.mViewportDraggingState,
state);
- check(mMgh.mViewportDraggingState.mZoomedInBeforeDrag, state);
+ check(!mMgh.mViewportDraggingState.mActivatedBeforeDrag, state);
} break;
- case STATE_DRAGGING_TMP: {
+ case STATE_ACTIVATED_ZOOMED_TMP: {
+ check(isActivated(), state);
check(isZoomed(), state);
check(mMgh.mCurrentState == mMgh.mViewportDraggingState,
state);
- check(!mMgh.mViewportDraggingState.mZoomedInBeforeDrag, state);
+ check(mMgh.mViewportDraggingState.mActivatedBeforeDrag, state);
} break;
case STATE_SHORTCUT_TRIGGERED: {
check(mMgh.mDetectingState.mShortcutTriggered, state);
+ check(isActivated(), state);
check(!isZoomed(), state);
} break;
case STATE_PANNING: {
- check(isZoomed(), state);
+ check(isActivated(), state);
check(mMgh.mCurrentState == mMgh.mPanningScalingState,
state);
check(!mMgh.mPanningScalingState.mScaling, state);
} break;
case STATE_SCALING_AND_PANNING: {
- check(isZoomed(), state);
+ check(isActivated(), state);
check(mMgh.mCurrentState == mMgh.mPanningScalingState,
state);
check(mMgh.mPanningScalingState.mScaling, state);
@@ -596,13 +619,13 @@
tap();
tap();
} break;
- case STATE_DRAGGING: {
- goFromStateIdleTo(STATE_ZOOMED_2TAPS);
+ case STATE_NON_ACTIVATED_ZOOMED_TMP: {
+ goFromStateIdleTo(STATE_2TAPS);
send(downEvent());
fastForward1sec();
} break;
- case STATE_DRAGGING_TMP: {
- goFromStateIdleTo(STATE_2TAPS);
+ case STATE_ACTIVATED_ZOOMED_TMP: {
+ goFromStateIdleTo(STATE_ZOOMED_2TAPS);
send(downEvent());
fastForward1sec();
} break;
@@ -654,13 +677,13 @@
case STATE_ZOOMED_2TAPS: {
tap();
} break;
- case STATE_DRAGGING: {
+ case STATE_NON_ACTIVATED_ZOOMED_TMP: {
+ send(upEvent());
+ } break;
+ case STATE_ACTIVATED_ZOOMED_TMP: {
send(upEvent());
returnToNormalFrom(STATE_ZOOMED);
} break;
- case STATE_DRAGGING_TMP: {
- send(upEvent());
- } break;
case STATE_SHORTCUT_TRIGGERED: {
triggerShortcut();
} break;
@@ -682,8 +705,12 @@
}
}
+ private boolean isActivated() {
+ return mMgh.mFullScreenMagnificationController.isActivated(DISPLAY_0);
+ }
+
private boolean isZoomed() {
- return mMgh.mFullScreenMagnificationController.isMagnifying(DISPLAY_0);
+ return mMgh.mFullScreenMagnificationController.getScale(DISPLAY_0) > 1.0f;
}
private int tapCount() {
@@ -770,10 +797,10 @@
private MotionEvent pointerEvent(int action, float x, float y) {
- return pointerEvent(action, new PointF[] {DEFAULT_POINT, new PointF(x, y)});
+ return pointerEvent(action, new PointF[] {DEFAULT_POINT, new PointF(x, y)}, 1);
}
- private MotionEvent pointerEvent(int action, PointF[] pointersPosition) {
+ private MotionEvent pointerEvent(int action, PointF[] pointersPosition, int changedIndex) {
final MotionEvent.PointerProperties[] PointerPropertiesArray =
new MotionEvent.PointerProperties[pointersPosition.length];
for (int i = 0; i < pointersPosition.length; i++) {
@@ -792,6 +819,8 @@
pointerCoordsArray[i] = pointerCoords;
}
+ action += (changedIndex << ACTION_POINTER_INDEX_SHIFT);
+
return MotionEvent.obtain(
/* downTime */ mClock.now(),
/* eventTime */ mClock.now(),
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java
index 2a80ce0..231b2f32 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java
@@ -495,16 +495,6 @@
}
@Test
- public void setScaleOneThroughExternalRequest_fullScreenEnabled_removeMagnificationButton()
- throws RemoteException {
- setMagnificationEnabled(MODE_FULLSCREEN);
- mScreenMagnificationController.setScaleAndCenter(TEST_DISPLAY, 1.0f,
- MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y, false, TEST_SERVICE_ID);
-
- verify(mWindowMagnificationManager).removeMagnificationButton(eq(TEST_DISPLAY));
- }
-
- @Test
public void onPerformScaleAction_magnifierEnabled_handleScaleChange() throws RemoteException {
final float newScale = 4.0f;
setMagnificationEnabled(MODE_WINDOW);
@@ -756,7 +746,7 @@
mMagnificationController.onWindowMagnificationActivationState(TEST_DISPLAY, true);
- assertFalse(mScreenMagnificationController.isMagnifying(TEST_DISPLAY));
+ verify(mScreenMagnificationController).reset(eq(TEST_DISPLAY), eq(false));
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
index e54a48b..1298e7b 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
@@ -1292,10 +1292,11 @@
unlockSystemUser();
try {
mAms.hasFeatures(
- null, // response
- AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS,
- new String[] {"feature1", "feature2"}, // features
- "testPackage"); // opPackageName
+ null, // response
+ AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS,
+ new String[] {"feature1", "feature2"}, // features
+ 0, // userId
+ "testPackage"); // opPackageName
fail("IllegalArgumentException expected. But no exception was thrown.");
} catch (IllegalArgumentException e) {
// IllegalArgumentException is expected.
@@ -1307,10 +1308,11 @@
unlockSystemUser();
try {
mAms.hasFeatures(
- mMockAccountManagerResponse, // response
- null, // account
- new String[] {"feature1", "feature2"}, // features
- "testPackage"); // opPackageName
+ mMockAccountManagerResponse, // response
+ null, // account
+ new String[] {"feature1", "feature2"}, // features
+ 0, // userId
+ "testPackage"); // opPackageName
fail("IllegalArgumentException expected. But no exception was thrown.");
} catch (IllegalArgumentException e) {
// IllegalArgumentException is expected.
@@ -1325,6 +1327,7 @@
mMockAccountManagerResponse, // response
AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, // account
null, // features
+ 0, // userId
"testPackage"); // opPackageName
fail("IllegalArgumentException expected. But no exception was thrown.");
} catch (IllegalArgumentException e) {
@@ -1341,6 +1344,7 @@
response, // response
AccountManagerServiceTestFixtures.ACCOUNT_ERROR, // account
AccountManagerServiceTestFixtures.ACCOUNT_FEATURES, // features
+ 0, // userId
"testPackage"); // opPackageName
waitForLatch(latch);
verify(mMockAccountManagerResponse).onError(
@@ -1357,6 +1361,7 @@
response, // response
AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, // account
AccountManagerServiceTestFixtures.ACCOUNT_FEATURES, // features
+ 0, // userId
"testPackage"); // opPackageName
waitForLatch(latch);
verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture());
diff --git a/services/tests/servicestests/src/com/android/server/am/CoreSettingsObserverTest.java b/services/tests/servicestests/src/com/android/server/am/CoreSettingsObserverTest.java
index 574aaf0..5f55f09 100644
--- a/services/tests/servicestests/src/com/android/server/am/CoreSettingsObserverTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/CoreSettingsObserverTest.java
@@ -97,6 +97,8 @@
mContentResolver = new MockContentResolver(mContext);
mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
when(mContext.getContentResolver()).thenReturn(mContentResolver);
+ when(mContext.getCacheDir()).thenReturn(originalContext.getCacheDir());
+ when(mContext.getAttributionSource()).thenReturn(originalContext.getAttributionSource());
when(mContext.getResources()).thenReturn(mResources);
// To prevent NullPointerException at the constructor of ActivityManagerConstants.
when(mResources.getStringArray(anyInt())).thenReturn(new String[0]);
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceParamsTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceParamsTest.java
index 3a27e3b..798650d 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceParamsTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceParamsTest.java
@@ -27,6 +27,7 @@
import android.companion.virtual.sensor.VirtualSensorConfig;
import android.os.Parcel;
import android.os.UserHandle;
+import android.platform.test.annotations.Presubmit;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -36,6 +37,7 @@
import java.util.List;
import java.util.Set;
+@Presubmit
@RunWith(AndroidJUnit4.class)
public class VirtualDeviceParamsTest {
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceTest.java
index f473086..bb28a36 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceTest.java
@@ -25,12 +25,14 @@
import android.companion.virtual.VirtualDevice;
import android.os.Parcel;
+import android.platform.test.annotations.Presubmit;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
+@Presubmit
@RunWith(AndroidJUnit4.class)
public class VirtualDeviceTest {
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java
index c270435..7b5af1e 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java
@@ -36,9 +36,11 @@
import android.media.PlayerBase;
import android.os.Parcel;
import android.os.RemoteException;
+import android.platform.test.annotations.Presubmit;
import android.util.ArraySet;
import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.FlakyTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.server.companion.virtual.GenericWindowPolicyController;
@@ -53,6 +55,7 @@
import java.util.ArrayList;
import java.util.List;
+@Presubmit
@RunWith(AndroidJUnit4.class)
public class VirtualAudioControllerTest {
private static final int APP1_UID = 100;
@@ -92,6 +95,7 @@
}
+ @FlakyTest(bugId = 265155135)
@Test
public void startListening_receivesCallback() throws RemoteException {
ArraySet<Integer> runningUids = new ArraySet<>();
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 61c3f13..210aeef 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -7396,7 +7396,7 @@
verify(getServices().alarmManager, times(1)).set(anyInt(), eq(PROFILE_OFF_DEADLINE), any());
// Now the user should see a warning notification.
verify(getServices().notificationManager, times(1))
- .notify(anyInt(), any());
+ .notifyAsUser(any(), anyInt(), any(), any());
// Apps shouldn't be suspended yet.
verifyZeroInteractions(getServices().ipackageManager);
clearInvocations(getServices().alarmManager);
@@ -7410,7 +7410,7 @@
verifyZeroInteractions(getServices().alarmManager);
// Now the user should see a notification about suspended apps.
verify(getServices().notificationManager, times(1))
- .notify(anyInt(), any());
+ .notifyAsUser(any(), anyInt(), any(), any());
// Verify that the apps are suspended.
verify(getServices().ipackageManager, times(1)).setPackagesSuspendedAsUser(
any(), eq(true), any(), any(), any(), any(), anyInt());
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/FakeEArcNativeWrapper.java b/services/tests/servicestests/src/com/android/server/hdmi/FakeEArcNativeWrapper.java
new file mode 100644
index 0000000..6f6cf8e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/hdmi/FakeEArcNativeWrapper.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.hdmi;
+
+import android.hardware.tv.hdmi.earc.IEArcStatus;
+
+final class FakeEArcNativeWrapper implements HdmiEarcController.EArcNativeWrapper {
+ private static final String TAG = "FakeEArcNativeWrapper";
+
+ private boolean mIsEArcEnabled = true;
+
+ @Override
+ public boolean nativeInit() {
+ return true;
+ }
+
+ @Override
+ public void nativeSetEArcEnabled(boolean enabled) {
+ mIsEArcEnabled = enabled;
+ }
+
+ @Override
+ public boolean nativeIsEArcEnabled() {
+ return mIsEArcEnabled;
+ }
+
+ @Override
+ public void nativeSetCallback(HdmiEarcController.EarcAidlCallback callback) {
+ }
+
+ @Override
+ public byte nativeGetState(int portId) {
+ return IEArcStatus.STATUS_IDLE;
+ }
+
+ @Override
+ public byte[] nativeGetLastReportedAudioCapabilities(int portId) {
+ return new byte[] {};
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/FakeNativeWrapper.java b/services/tests/servicestests/src/com/android/server/hdmi/FakeNativeWrapper.java
index 29eccd4..bb50a89 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/FakeNativeWrapper.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/FakeNativeWrapper.java
@@ -30,7 +30,7 @@
import java.util.List;
import java.util.Map;
-/** Fake {@link NativeWrapper} useful for testing. */
+/** Fake {@link NativeWrapper} for the HDMI CEC HAL, useful for testing. */
final class FakeNativeWrapper implements NativeWrapper {
private static final String TAG = "FakeNativeWrapper";
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
index 233fd6e..cb1e78b 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
@@ -90,6 +90,8 @@
private HdmiCecController mHdmiCecController;
private HdmiCecLocalDeviceTv mHdmiCecLocalDeviceTv;
private FakeNativeWrapper mNativeWrapper;
+ private HdmiEarcController mHdmiEarcController;
+ private FakeEArcNativeWrapper mEArcNativeWrapper;
private FakePowerManagerWrapper mPowerManager;
private Looper mMyLooper;
private TestLooper mTestLooper = new TestLooper();
@@ -185,6 +187,10 @@
mHdmiCecController = HdmiCecController.createWithNativeWrapper(
mHdmiControlService, mNativeWrapper, mHdmiControlService.getAtomWriter());
mHdmiControlService.setCecController(mHdmiCecController);
+ mEArcNativeWrapper = new FakeEArcNativeWrapper();
+ mHdmiEarcController = HdmiEarcController.createWithNativeWrapper(
+ mHdmiControlService, mEArcNativeWrapper);
+ mHdmiControlService.setEarcController(mHdmiEarcController);
mHdmiControlService.setHdmiMhlController(HdmiMhlControllerStub.create(mHdmiControlService));
HdmiPortInfo[] hdmiPortInfos = new HdmiPortInfo[2];
hdmiPortInfos[0] =
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
index 6c77405..cd6dfbf 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
@@ -87,6 +87,8 @@
private MockAudioSystemDevice mAudioSystemDeviceSpy;
private MockPlaybackDevice mPlaybackDeviceSpy;
private FakeNativeWrapper mNativeWrapper;
+ private HdmiEarcController mHdmiEarcController;
+ private FakeEArcNativeWrapper mEArcNativeWrapper;
private FakePowerManagerWrapper mPowerManager;
private Looper mMyLooper;
private TestLooper mTestLooper = new TestLooper();
@@ -126,6 +128,10 @@
mHdmiCecController = HdmiCecController.createWithNativeWrapper(
mHdmiControlServiceSpy, mNativeWrapper, mHdmiControlServiceSpy.getAtomWriter());
mHdmiControlServiceSpy.setCecController(mHdmiCecController);
+ mEArcNativeWrapper = new FakeEArcNativeWrapper();
+ mHdmiEarcController = HdmiEarcController.createWithNativeWrapper(
+ mHdmiControlServiceSpy, mEArcNativeWrapper);
+ mHdmiControlServiceSpy.setEarcController(mHdmiEarcController);
mHdmiControlServiceSpy.setHdmiMhlController(HdmiMhlControllerStub.create(
mHdmiControlServiceSpy));
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiEarcLocalDeviceTxTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiEarcLocalDeviceTxTest.java
index c79e219..4ac23f8 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiEarcLocalDeviceTxTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiEarcLocalDeviceTxTest.java
@@ -68,6 +68,8 @@
private HdmiCecController mHdmiCecController;
private HdmiEarcLocalDevice mHdmiEarcLocalDeviceTx;
private FakeNativeWrapper mNativeWrapper;
+ private HdmiEarcController mHdmiEarcController;
+ private FakeEArcNativeWrapper mEArcNativeWrapper;
private FakePowerManagerWrapper mPowerManager;
private byte[] mEarcCapabilities = new byte[]{
0x01, 0x01, 0x1a, 0x35, 0x0f, 0x7f, 0x07, 0x15, 0x07, 0x50, 0x3d, 0x1f, (byte) 0xc0,
@@ -126,6 +128,10 @@
mHdmiCecController = HdmiCecController.createWithNativeWrapper(
mHdmiControlService, mNativeWrapper, mHdmiControlService.getAtomWriter());
mHdmiControlService.setCecController(mHdmiCecController);
+ mEArcNativeWrapper = new FakeEArcNativeWrapper();
+ mHdmiEarcController = HdmiEarcController.createWithNativeWrapper(
+ mHdmiControlService, mEArcNativeWrapper);
+ mHdmiControlService.setEarcController(mHdmiEarcController);
mHdmiControlService.setHdmiMhlController(HdmiMhlControllerStub.create(mHdmiControlService));
mHdmiControlService.initService();
mHdmiControlService.onBootPhase(PHASE_SYSTEM_SERVICES_READY);
diff --git a/services/tests/servicestests/src/com/android/server/input/BatteryControllerTests.kt b/services/tests/servicestests/src/com/android/server/input/BatteryControllerTests.kt
index ecd9d89..3ce747f 100644
--- a/services/tests/servicestests/src/com/android/server/input/BatteryControllerTests.kt
+++ b/services/tests/servicestests/src/com/android/server/input/BatteryControllerTests.kt
@@ -16,7 +16,9 @@
package com.android.server.input
+import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
+import android.bluetooth.BluetoothManager
import android.content.Context
import android.content.ContextWrapper
import android.hardware.BatteryState.STATUS_CHARGING
@@ -246,6 +248,11 @@
notifyDeviceChanged(deviceId, hasBattery, supportsUsi)
}
+ private fun createBluetoothDevice(address: String): BluetoothDevice {
+ return context.getSystemService(BluetoothManager::class.java)!!
+ .adapter.getRemoteDevice(address)
+ }
+
@After
fun tearDown() {
InputManager.clearInstance()
@@ -656,29 +663,31 @@
addInputDevice(SECOND_BT_DEVICE_ID)
testLooper.dispatchNext()
- // Ensure that a BT battery listener is not added when there are no monitored BT devices.
- verify(bluetoothBatteryManager, never()).addListener(any())
+ // Listen to a non-Bluetooth device and ensure that the BT battery listener is not added
+ // when there are no monitored BT devices.
+ val listener = createMockListener()
+ batteryController.registerBatteryListener(DEVICE_ID, listener, PID)
+ verify(bluetoothBatteryManager, never()).addBatteryListener(any())
val bluetoothListener = ArgumentCaptor.forClass(BluetoothBatteryListener::class.java)
- val listener = createMockListener()
// The BT battery listener is added when the first BT input device is monitored.
batteryController.registerBatteryListener(BT_DEVICE_ID, listener, PID)
- verify(bluetoothBatteryManager).addListener(bluetoothListener.capture())
+ verify(bluetoothBatteryManager).addBatteryListener(bluetoothListener.capture())
// The BT listener is only added once for all BT devices.
batteryController.registerBatteryListener(SECOND_BT_DEVICE_ID, listener, PID)
- verify(bluetoothBatteryManager, times(1)).addListener(any())
+ verify(bluetoothBatteryManager, times(1)).addBatteryListener(any())
// The BT listener is only removed when there are no monitored BT devices.
batteryController.unregisterBatteryListener(BT_DEVICE_ID, listener, PID)
- verify(bluetoothBatteryManager, never()).removeListener(any())
+ verify(bluetoothBatteryManager, never()).removeBatteryListener(any())
`when`(iInputManager.getInputDeviceBluetoothAddress(SECOND_BT_DEVICE_ID))
.thenReturn(null)
notifyDeviceChanged(SECOND_BT_DEVICE_ID)
testLooper.dispatchNext()
- verify(bluetoothBatteryManager).removeListener(bluetoothListener.value)
+ verify(bluetoothBatteryManager).removeBatteryListener(bluetoothListener.value)
}
@Test
@@ -690,15 +699,14 @@
val bluetoothListener = ArgumentCaptor.forClass(BluetoothBatteryListener::class.java)
val listener = createMockListener()
batteryController.registerBatteryListener(BT_DEVICE_ID, listener, PID)
- verify(bluetoothBatteryManager).addListener(bluetoothListener.capture())
+ verify(bluetoothBatteryManager).addBatteryListener(bluetoothListener.capture())
listener.verifyNotified(BT_DEVICE_ID, capacity = 0.21f)
// When the state has not changed, the listener is not notified again.
- bluetoothListener.value!!.onBluetoothBatteryChanged(TIMESTAMP, "AA:BB:CC:DD:EE:FF")
+ bluetoothListener.value!!.onBluetoothBatteryChanged(TIMESTAMP, "AA:BB:CC:DD:EE:FF", 21)
listener.verifyNotified(BT_DEVICE_ID, mode = times(1), capacity = 0.21f)
- `when`(bluetoothBatteryManager.getBatteryLevel(eq("AA:BB:CC:DD:EE:FF"))).thenReturn(25)
- bluetoothListener.value!!.onBluetoothBatteryChanged(TIMESTAMP, "AA:BB:CC:DD:EE:FF")
+ bluetoothListener.value!!.onBluetoothBatteryChanged(TIMESTAMP, "AA:BB:CC:DD:EE:FF", 25)
listener.verifyNotified(BT_DEVICE_ID, capacity = 0.25f)
}
@@ -717,7 +725,7 @@
// When the device is first monitored and both native and BT battery is available,
// the latter is used.
batteryController.registerBatteryListener(BT_DEVICE_ID, listener, PID)
- verify(bluetoothBatteryManager).addListener(bluetoothListener.capture())
+ verify(bluetoothBatteryManager).addBatteryListener(bluetoothListener.capture())
verify(uEventManager).addListener(uEventListener.capture(), any())
listener.verifyNotified(BT_DEVICE_ID, capacity = 0.21f)
assertThat("battery state matches", batteryController.getBatteryState(BT_DEVICE_ID),
@@ -744,25 +752,144 @@
val uEventListener = ArgumentCaptor.forClass(UEventBatteryListener::class.java)
batteryController.registerBatteryListener(BT_DEVICE_ID, listener, PID)
- verify(bluetoothBatteryManager).addListener(bluetoothListener.capture())
+ verify(bluetoothBatteryManager).addBatteryListener(bluetoothListener.capture())
verify(uEventManager).addListener(uEventListener.capture(), any())
listener.verifyNotified(BT_DEVICE_ID, capacity = 0.21f)
// Fall back to the native state when BT is off.
- `when`(bluetoothBatteryManager.getBatteryLevel(eq("AA:BB:CC:DD:EE:FF")))
- .thenReturn(BluetoothDevice.BATTERY_LEVEL_BLUETOOTH_OFF)
- bluetoothListener.value!!.onBluetoothBatteryChanged(TIMESTAMP, "AA:BB:CC:DD:EE:FF")
+ bluetoothListener.value!!.onBluetoothBatteryChanged(TIMESTAMP, "AA:BB:CC:DD:EE:FF",
+ BluetoothDevice.BATTERY_LEVEL_BLUETOOTH_OFF)
listener.verifyNotified(BT_DEVICE_ID, capacity = 0.98f)
- `when`(bluetoothBatteryManager.getBatteryLevel(eq("AA:BB:CC:DD:EE:FF"))).thenReturn(22)
- bluetoothListener.value!!.onBluetoothBatteryChanged(TIMESTAMP, "AA:BB:CC:DD:EE:FF")
- verify(bluetoothBatteryManager).addListener(bluetoothListener.capture())
+ bluetoothListener.value!!.onBluetoothBatteryChanged(TIMESTAMP, "AA:BB:CC:DD:EE:FF", 22)
+ verify(bluetoothBatteryManager).addBatteryListener(bluetoothListener.capture())
listener.verifyNotified(BT_DEVICE_ID, capacity = 0.22f)
// Fall back to the native state when BT battery is unknown.
- `when`(bluetoothBatteryManager.getBatteryLevel(eq("AA:BB:CC:DD:EE:FF")))
- .thenReturn(BluetoothDevice.BATTERY_LEVEL_UNKNOWN)
- bluetoothListener.value!!.onBluetoothBatteryChanged(TIMESTAMP, "AA:BB:CC:DD:EE:FF")
+ bluetoothListener.value!!.onBluetoothBatteryChanged(TIMESTAMP, "AA:BB:CC:DD:EE:FF",
+ BluetoothDevice.BATTERY_LEVEL_UNKNOWN)
listener.verifyNotified(BT_DEVICE_ID, mode = times(2), capacity = 0.98f)
}
+
+ @Test
+ fun testRegisterBluetoothMetadataListenerForMonitoredBluetoothDevices() {
+ `when`(iInputManager.getInputDeviceBluetoothAddress(BT_DEVICE_ID))
+ .thenReturn("AA:BB:CC:DD:EE:FF")
+ `when`(iInputManager.getInputDeviceBluetoothAddress(SECOND_BT_DEVICE_ID))
+ .thenReturn("11:22:33:44:55:66")
+ addInputDevice(BT_DEVICE_ID)
+ testLooper.dispatchNext()
+ addInputDevice(SECOND_BT_DEVICE_ID)
+ testLooper.dispatchNext()
+
+ // Listen to a non-Bluetooth device and ensure that the metadata listener is not added when
+ // there are no monitored BT devices.
+ val listener = createMockListener()
+ batteryController.registerBatteryListener(DEVICE_ID, listener, PID)
+ verify(bluetoothBatteryManager, never()).addMetadataListener(any(), any())
+
+ val metadataListener1 = ArgumentCaptor.forClass(
+ BluetoothAdapter.OnMetadataChangedListener::class.java)
+ val metadataListener2 = ArgumentCaptor.forClass(
+ BluetoothAdapter.OnMetadataChangedListener::class.java)
+
+ // The metadata listener is added when the first BT input device is monitored.
+ batteryController.registerBatteryListener(BT_DEVICE_ID, listener, PID)
+ verify(bluetoothBatteryManager)
+ .addMetadataListener(eq("AA:BB:CC:DD:EE:FF"), metadataListener1.capture())
+
+ // There is one metadata listener added for each BT device.
+ batteryController.registerBatteryListener(SECOND_BT_DEVICE_ID, listener, PID)
+ verify(bluetoothBatteryManager)
+ .addMetadataListener(eq("11:22:33:44:55:66"), metadataListener2.capture())
+
+ // The metadata listener is removed when the device is no longer monitored.
+ batteryController.unregisterBatteryListener(BT_DEVICE_ID, listener, PID)
+ verify(bluetoothBatteryManager)
+ .removeMetadataListener("AA:BB:CC:DD:EE:FF", metadataListener1.value)
+
+ `when`(iInputManager.getInputDeviceBluetoothAddress(SECOND_BT_DEVICE_ID))
+ .thenReturn(null)
+ notifyDeviceChanged(SECOND_BT_DEVICE_ID)
+ testLooper.dispatchNext()
+ verify(bluetoothBatteryManager)
+ .removeMetadataListener("11:22:33:44:55:66", metadataListener2.value)
+ }
+
+ @Test
+ fun testNotifiesBluetoothMetadataBatteryChanges() {
+ `when`(iInputManager.getInputDeviceBluetoothAddress(BT_DEVICE_ID))
+ .thenReturn("AA:BB:CC:DD:EE:FF")
+ `when`(bluetoothBatteryManager.getMetadata("AA:BB:CC:DD:EE:FF",
+ BluetoothDevice.METADATA_MAIN_BATTERY))
+ .thenReturn("21".toByteArray())
+ addInputDevice(BT_DEVICE_ID)
+ val metadataListener = ArgumentCaptor.forClass(
+ BluetoothAdapter.OnMetadataChangedListener::class.java)
+ val listener = createMockListener()
+ val bluetoothDevice = createBluetoothDevice("AA:BB:CC:DD:EE:FF")
+ batteryController.registerBatteryListener(BT_DEVICE_ID, listener, PID)
+ verify(bluetoothBatteryManager)
+ .addMetadataListener(eq("AA:BB:CC:DD:EE:FF"), metadataListener.capture())
+ listener.verifyNotified(BT_DEVICE_ID, capacity = 0.21f, status = STATUS_UNKNOWN)
+
+ // When the state has not changed, the listener is not notified again.
+ metadataListener.value!!.onMetadataChanged(
+ bluetoothDevice, BluetoothDevice.METADATA_MAIN_BATTERY, "21".toByteArray())
+ listener.verifyNotified(BT_DEVICE_ID, mode = times(1), capacity = 0.21f)
+
+ metadataListener.value!!.onMetadataChanged(
+ bluetoothDevice, BluetoothDevice.METADATA_MAIN_BATTERY, "25".toByteArray())
+ listener.verifyNotified(BT_DEVICE_ID, capacity = 0.25f, status = STATUS_UNKNOWN)
+
+ metadataListener.value!!.onMetadataChanged(
+ bluetoothDevice, BluetoothDevice.METADATA_MAIN_CHARGING, "true".toByteArray())
+ listener.verifyNotified(BT_DEVICE_ID, capacity = 0.25f, status = STATUS_CHARGING)
+
+ metadataListener.value!!.onMetadataChanged(
+ bluetoothDevice, BluetoothDevice.METADATA_MAIN_CHARGING, "false".toByteArray())
+ listener.verifyNotified(BT_DEVICE_ID, capacity = 0.25f, status = STATUS_DISCHARGING)
+
+ metadataListener.value!!.onMetadataChanged(
+ bluetoothDevice, BluetoothDevice.METADATA_MAIN_CHARGING, null)
+ listener.verifyNotified(BT_DEVICE_ID, mode = times(2), capacity = 0.25f,
+ status = STATUS_UNKNOWN)
+ }
+
+ @Test
+ fun testBluetoothMetadataBatteryIsPrioritized() {
+ `when`(iInputManager.getInputDeviceBluetoothAddress(BT_DEVICE_ID))
+ .thenReturn("AA:BB:CC:DD:EE:FF")
+ `when`(bluetoothBatteryManager.getBatteryLevel(eq("AA:BB:CC:DD:EE:FF"))).thenReturn(21)
+ `when`(bluetoothBatteryManager.getMetadata("AA:BB:CC:DD:EE:FF",
+ BluetoothDevice.METADATA_MAIN_BATTERY))
+ .thenReturn("22".toByteArray())
+ addInputDevice(BT_DEVICE_ID)
+ val bluetoothListener = ArgumentCaptor.forClass(BluetoothBatteryListener::class.java)
+ val metadataListener = ArgumentCaptor.forClass(
+ BluetoothAdapter.OnMetadataChangedListener::class.java)
+ val listener = createMockListener()
+ val bluetoothDevice = createBluetoothDevice("AA:BB:CC:DD:EE:FF")
+ batteryController.registerBatteryListener(BT_DEVICE_ID, listener, PID)
+
+ verify(bluetoothBatteryManager).addBatteryListener(bluetoothListener.capture())
+ verify(bluetoothBatteryManager)
+ .addMetadataListener(eq("AA:BB:CC:DD:EE:FF"), metadataListener.capture())
+ listener.verifyNotified(BT_DEVICE_ID, capacity = 0.22f)
+
+ // A change in the Bluetooth battery level has no effect while there is a valid battery
+ // level obtained through the metadata.
+ bluetoothListener.value!!.onBluetoothBatteryChanged(TIMESTAMP, "AA:BB:CC:DD:EE:FF", 23)
+ listener.verifyNotified(BT_DEVICE_ID, mode = never(), capacity = 0.23f)
+
+ metadataListener.value!!.onMetadataChanged(
+ bluetoothDevice, BluetoothDevice.METADATA_MAIN_BATTERY, "24".toByteArray())
+ listener.verifyNotified(BT_DEVICE_ID, capacity = 0.24f)
+
+ // When the battery level from the metadata is no longer valid, we fall back to using the
+ // Bluetooth battery level.
+ metadataListener.value!!.onMetadataChanged(
+ bluetoothDevice, BluetoothDevice.METADATA_MAIN_BATTERY, null)
+ listener.verifyNotified(BT_DEVICE_ID, capacity = 0.23f)
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/input/KeyboardBacklightControllerTests.kt b/services/tests/servicestests/src/com/android/server/input/KeyboardBacklightControllerTests.kt
index b5dad94..1d23e12 100644
--- a/services/tests/servicestests/src/com/android/server/input/KeyboardBacklightControllerTests.kt
+++ b/services/tests/servicestests/src/com/android/server/input/KeyboardBacklightControllerTests.kt
@@ -28,7 +28,8 @@
import android.platform.test.annotations.Presubmit
import android.view.InputDevice
import androidx.test.core.app.ApplicationProvider
-import com.android.server.input.KeyboardBacklightController.BRIGHTNESS_LEVELS
+import com.android.server.input.KeyboardBacklightController.BRIGHTNESS_VALUE_FOR_LEVEL
+import com.android.server.input.KeyboardBacklightController.USER_INACTIVITY_THRESHOLD_MILLIS
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
@@ -78,6 +79,7 @@
const val DEVICE_ID = 1
const val LIGHT_ID = 2
const val SECOND_LIGHT_ID = 3
+ const val MAX_BRIGHTNESS = 255
}
@get:Rule
@@ -118,10 +120,6 @@
val args = it.arguments
lightColorMap.put(args[1] as Int, args[2] as Int)
}
- `when`(native.getLightColor(anyInt(), anyInt())).then {
- val args = it.arguments
- lightColorMap.getOrDefault(args[1] as Int, -1)
- }
lightColorMap.clear()
}
@@ -137,21 +135,17 @@
`when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
`when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
- // Initially backlight is at min
- lightColorMap[LIGHT_ID] = Color.argb(BRIGHTNESS_LEVELS.first(), 0, 0, 0)
- val brightnessLevelsArray = BRIGHTNESS_LEVELS.toTypedArray()
- for (level in 1 until brightnessLevelsArray.size) {
- keyboardBacklightController.incrementKeyboardBacklight(DEVICE_ID)
- testLooper.dispatchNext()
+ for (level in 1 until BRIGHTNESS_VALUE_FOR_LEVEL.size) {
+ incrementKeyboardBacklight(DEVICE_ID)
assertEquals(
"Light value for level $level mismatched",
- Color.argb(brightnessLevelsArray[level], 0, 0, 0),
+ Color.argb(BRIGHTNESS_VALUE_FOR_LEVEL[level], 0, 0, 0),
lightColorMap[LIGHT_ID]
)
assertEquals(
"Light value for level $level must be correctly stored in the datastore",
- brightnessLevelsArray[level],
+ BRIGHTNESS_VALUE_FOR_LEVEL[level],
dataStore.getKeyboardBacklightBrightness(
keyboardWithBacklight.descriptor,
LIGHT_ID
@@ -159,72 +153,49 @@
)
}
- for (level in brightnessLevelsArray.size - 2 downTo 0) {
- keyboardBacklightController.decrementKeyboardBacklight(DEVICE_ID)
- testLooper.dispatchNext()
- assertEquals(
- "Light value for level $level mismatched",
- Color.argb(brightnessLevelsArray[level], 0, 0, 0),
- lightColorMap[LIGHT_ID]
- )
- assertEquals(
- "Light value for level $level must be correctly stored in the datastore",
- brightnessLevelsArray[level],
- dataStore.getKeyboardBacklightBrightness(
- keyboardWithBacklight.descriptor,
- LIGHT_ID
- ).asInt
- )
- }
- }
-
- @Test
- fun testKeyboardBacklightIncrementAboveMaxLevel() {
- val keyboardWithBacklight = createKeyboard(DEVICE_ID)
- val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
- `when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
- `when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
- keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
- // Initially backlight is at max
- lightColorMap[LIGHT_ID] = Color.argb(BRIGHTNESS_LEVELS.last(), 0, 0, 0)
-
- keyboardBacklightController.incrementKeyboardBacklight(DEVICE_ID)
- testLooper.dispatchNext()
+ // Increment above max level
+ incrementKeyboardBacklight(DEVICE_ID)
assertEquals(
"Light value for max level mismatched",
- Color.argb(BRIGHTNESS_LEVELS.last(), 0, 0, 0),
+ Color.argb(MAX_BRIGHTNESS, 0, 0, 0),
lightColorMap[LIGHT_ID]
)
assertEquals(
"Light value for max level must be correctly stored in the datastore",
- BRIGHTNESS_LEVELS.last(),
+ MAX_BRIGHTNESS,
dataStore.getKeyboardBacklightBrightness(
keyboardWithBacklight.descriptor,
LIGHT_ID
).asInt
)
- }
- @Test
- fun testKeyboardBacklightDecrementBelowMin() {
- val keyboardWithBacklight = createKeyboard(DEVICE_ID)
- val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
- `when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
- `when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
- keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
- // Initially backlight is at min
- lightColorMap[LIGHT_ID] = Color.argb(BRIGHTNESS_LEVELS.first(), 0, 0, 0)
+ for (level in BRIGHTNESS_VALUE_FOR_LEVEL.size - 2 downTo 0) {
+ decrementKeyboardBacklight(DEVICE_ID)
+ assertEquals(
+ "Light value for level $level mismatched",
+ Color.argb(BRIGHTNESS_VALUE_FOR_LEVEL[level], 0, 0, 0),
+ lightColorMap[LIGHT_ID]
+ )
+ assertEquals(
+ "Light value for level $level must be correctly stored in the datastore",
+ BRIGHTNESS_VALUE_FOR_LEVEL[level],
+ dataStore.getKeyboardBacklightBrightness(
+ keyboardWithBacklight.descriptor,
+ LIGHT_ID
+ ).asInt
+ )
+ }
- keyboardBacklightController.decrementKeyboardBacklight(DEVICE_ID)
- testLooper.dispatchNext()
+ // Decrement below min level
+ decrementKeyboardBacklight(DEVICE_ID)
assertEquals(
"Light value for min level mismatched",
- Color.argb(BRIGHTNESS_LEVELS.first(), 0, 0, 0),
+ Color.argb(0, 0, 0, 0),
lightColorMap[LIGHT_ID]
)
assertEquals(
"Light value for min level must be correctly stored in the datastore",
- BRIGHTNESS_LEVELS.first(),
+ 0,
dataStore.getKeyboardBacklightBrightness(
keyboardWithBacklight.descriptor,
LIGHT_ID
@@ -240,7 +211,7 @@
`when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardInputLight))
keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
- keyboardBacklightController.incrementKeyboardBacklight(DEVICE_ID)
+ incrementKeyboardBacklight(DEVICE_ID)
assertTrue("Non Keyboard backlights should not change", lightColorMap.isEmpty())
}
@@ -258,8 +229,7 @@
)
keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
- keyboardBacklightController.incrementKeyboardBacklight(DEVICE_ID)
- testLooper.dispatchNext()
+ incrementKeyboardBacklight(DEVICE_ID)
assertEquals("Only keyboard backlights should change", 1, lightColorMap.size)
assertNotNull("Keyboard backlight should change", lightColorMap[LIGHT_ID])
assertNull("Input lights should not change", lightColorMap[SECOND_LIGHT_ID])
@@ -275,14 +245,15 @@
dataStore.setKeyboardBacklightBrightness(
keyboardWithBacklight.descriptor,
LIGHT_ID,
- BRIGHTNESS_LEVELS.last()
+ MAX_BRIGHTNESS
)
- lightColorMap.clear()
keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
+ keyboardBacklightController.notifyUserActivity()
+ testLooper.dispatchNext()
assertEquals(
"Keyboard backlight level should be restored to the level saved in the data store",
- Color.argb(BRIGHTNESS_LEVELS.last(), 0, 0, 0),
+ Color.argb(MAX_BRIGHTNESS, 0, 0, 0),
lightColorMap[LIGHT_ID]
)
}
@@ -295,11 +266,12 @@
dataStore.setKeyboardBacklightBrightness(
keyboardWithBacklight.descriptor,
LIGHT_ID,
- BRIGHTNESS_LEVELS.last()
+ MAX_BRIGHTNESS
)
- lightColorMap.clear()
keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
+ keyboardBacklightController.notifyUserActivity()
+ testLooper.dispatchNext()
assertTrue(
"Keyboard backlight should not be changed until its added",
lightColorMap.isEmpty()
@@ -307,22 +279,22 @@
`when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
keyboardBacklightController.onInputDeviceChanged(DEVICE_ID)
+ keyboardBacklightController.notifyUserActivity()
+ testLooper.dispatchNext()
assertEquals(
"Keyboard backlight level should be restored to the level saved in the data store",
- Color.argb(BRIGHTNESS_LEVELS.last(), 0, 0, 0),
+ Color.argb(MAX_BRIGHTNESS, 0, 0, 0),
lightColorMap[LIGHT_ID]
)
}
@Test
- fun testKeyboardBacklightT_registerUnregisterListener() {
+ fun testKeyboardBacklight_registerUnregisterListener() {
val keyboardWithBacklight = createKeyboard(DEVICE_ID)
val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
`when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
`when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
- // Initially backlight is at min
- lightColorMap[LIGHT_ID] = Color.argb(BRIGHTNESS_LEVELS.first(), 0, 0, 0)
// Register backlight listener
val listener = KeyboardBacklightListener()
@@ -343,8 +315,8 @@
lastBacklightState!!.brightnessLevel
)
assertEquals(
- "Backlight state maxBrightnessLevel should be " + (BRIGHTNESS_LEVELS.size - 1),
- (BRIGHTNESS_LEVELS.size - 1),
+ "Backlight state maxBrightnessLevel should be " + (BRIGHTNESS_VALUE_FOR_LEVEL.size - 1),
+ (BRIGHTNESS_VALUE_FOR_LEVEL.size - 1),
lastBacklightState!!.maxBrightnessLevel
)
assertEquals(
@@ -357,12 +329,70 @@
keyboardBacklightController.unregisterKeyboardBacklightListener(listener, 0)
lastBacklightState = null
- keyboardBacklightController.incrementKeyboardBacklight(DEVICE_ID)
- testLooper.dispatchNext()
+ incrementKeyboardBacklight(DEVICE_ID)
assertNull("Listener should not receive any updates", lastBacklightState)
}
+ @Test
+ fun testKeyboardBacklight_userActivity() {
+ val keyboardWithBacklight = createKeyboard(DEVICE_ID)
+ val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
+ `when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
+ `when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
+ dataStore.setKeyboardBacklightBrightness(
+ keyboardWithBacklight.descriptor,
+ LIGHT_ID,
+ MAX_BRIGHTNESS
+ )
+
+ keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
+ keyboardBacklightController.notifyUserActivity()
+ testLooper.dispatchNext()
+ assertEquals(
+ "Keyboard backlight level should be restored to the level saved in the data store",
+ Color.argb(MAX_BRIGHTNESS, 0, 0, 0),
+ lightColorMap[LIGHT_ID]
+ )
+
+ testLooper.moveTimeForward(USER_INACTIVITY_THRESHOLD_MILLIS + 1000)
+ testLooper.dispatchNext()
+ assertEquals(
+ "Keyboard backlight level should be turned off after inactivity",
+ 0,
+ lightColorMap[LIGHT_ID]
+ )
+ }
+
+ @Test
+ fun testKeyboardBacklight_displayOnOff() {
+ val keyboardWithBacklight = createKeyboard(DEVICE_ID)
+ val keyboardBacklight = createLight(LIGHT_ID, Light.LIGHT_TYPE_KEYBOARD_BACKLIGHT)
+ `when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
+ `when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
+ dataStore.setKeyboardBacklightBrightness(
+ keyboardWithBacklight.descriptor,
+ LIGHT_ID,
+ MAX_BRIGHTNESS
+ )
+
+ keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
+ keyboardBacklightController.handleInteractiveStateChange(true /* isDisplayOn */)
+ assertEquals(
+ "Keyboard backlight level should be restored to the level saved in the data " +
+ "store when display turned on",
+ Color.argb(MAX_BRIGHTNESS, 0, 0, 0),
+ lightColorMap[LIGHT_ID]
+ )
+
+ keyboardBacklightController.handleInteractiveStateChange(false /* isDisplayOn */)
+ assertEquals(
+ "Keyboard backlight level should be turned off after display is turned off",
+ 0,
+ lightColorMap[LIGHT_ID]
+ )
+ }
+
inner class KeyboardBacklightListener : IKeyboardBacklightListener.Stub() {
override fun onBrightnessChanged(
deviceId: Int,
@@ -378,6 +408,18 @@
}
}
+ private fun incrementKeyboardBacklight(deviceId: Int) {
+ keyboardBacklightController.incrementKeyboardBacklight(deviceId)
+ keyboardBacklightController.notifyUserActivity()
+ testLooper.dispatchAll()
+ }
+
+ private fun decrementKeyboardBacklight(deviceId: Int) {
+ keyboardBacklightController.decrementKeyboardBacklight(deviceId)
+ keyboardBacklightController.notifyUserActivity()
+ testLooper.dispatchAll()
+ }
+
class KeyboardBacklightState(
val deviceId: Int,
val brightnessLevel: Int,
diff --git a/services/tests/servicestests/src/com/android/server/input/KeyboardLayoutManagerTests.kt b/services/tests/servicestests/src/com/android/server/input/KeyboardLayoutManagerTests.kt
new file mode 100644
index 0000000..34540c3
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/input/KeyboardLayoutManagerTests.kt
@@ -0,0 +1,820 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.input
+
+import android.content.Context
+import android.content.ContextWrapper
+import android.content.pm.ActivityInfo
+import android.content.pm.ApplicationInfo
+import android.content.pm.PackageManager
+import android.content.pm.ResolveInfo
+import android.content.pm.ServiceInfo
+import android.hardware.input.IInputManager
+import android.hardware.input.InputManager
+import android.hardware.input.KeyboardLayout
+import android.icu.lang.UScript
+import android.icu.util.ULocale
+import android.os.Bundle
+import android.os.test.TestLooper
+import android.platform.test.annotations.Presubmit
+import android.provider.Settings
+import android.view.InputDevice
+import android.view.inputmethod.InputMethodInfo
+import android.view.inputmethod.InputMethodSubtype
+import androidx.test.core.R
+import androidx.test.core.app.ApplicationProvider
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNotEquals
+import org.junit.Assert.assertNull
+import org.junit.Assert.assertTrue
+import org.junit.Assert.assertThrows
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.junit.MockitoJUnit
+import java.io.FileNotFoundException
+import java.io.FileOutputStream
+import java.io.IOException
+import java.io.InputStream
+import java.util.Locale
+
+private fun createKeyboard(
+ deviceId: Int,
+ vendorId: Int,
+ productId: Int,
+ languageTag: String,
+ layoutType: String
+): InputDevice =
+ InputDevice.Builder()
+ .setId(deviceId)
+ .setName("Device $deviceId")
+ .setDescriptor("descriptor $deviceId")
+ .setSources(InputDevice.SOURCE_KEYBOARD)
+ .setKeyboardType(InputDevice.KEYBOARD_TYPE_ALPHABETIC)
+ .setExternal(true)
+ .setVendorId(vendorId)
+ .setProductId(productId)
+ .setKeyboardLanguageTag(languageTag)
+ .setKeyboardLayoutType(layoutType)
+ .build()
+
+/**
+ * Tests for {@link Default UI} and {@link New UI}.
+ *
+ * Build/Install/Run:
+ * atest FrameworksServicesTests:KeyboardLayoutManagerTests
+ */
+@Presubmit
+class KeyboardLayoutManagerTests {
+ companion object {
+ const val DEVICE_ID = 1
+ const val VENDOR_SPECIFIC_DEVICE_ID = 2
+ const val ENGLISH_DVORAK_DEVICE_ID = 3
+ const val USER_ID = 4
+ const val IME_ID = "ime_id"
+ const val PACKAGE_NAME = "KeyboardLayoutManagerTests"
+ const val RECEIVER_NAME = "DummyReceiver"
+ private const val ENGLISH_US_LAYOUT_NAME = "keyboard_layout_english_us"
+ private const val ENGLISH_UK_LAYOUT_NAME = "keyboard_layout_english_uk"
+ private const val VENDOR_SPECIFIC_LAYOUT_NAME = "keyboard_layout_vendorId:1,productId:1"
+ }
+
+ private val ENGLISH_US_LAYOUT_DESCRIPTOR = createLayoutDescriptor(ENGLISH_US_LAYOUT_NAME)
+ private val ENGLISH_UK_LAYOUT_DESCRIPTOR = createLayoutDescriptor(ENGLISH_UK_LAYOUT_NAME)
+ private val VENDOR_SPECIFIC_LAYOUT_DESCRIPTOR =
+ createLayoutDescriptor(VENDOR_SPECIFIC_LAYOUT_NAME)
+
+ @get:Rule
+ val rule = MockitoJUnit.rule()!!
+
+ @Mock
+ private lateinit var iInputManager: IInputManager
+
+ @Mock
+ private lateinit var native: NativeInputManagerService
+
+ @Mock
+ private lateinit var packageManager: PackageManager
+ private lateinit var keyboardLayoutManager: KeyboardLayoutManager
+
+ private lateinit var imeInfo: InputMethodInfo
+ private var nextImeSubtypeId = 0
+ private lateinit var context: Context
+ private lateinit var dataStore: PersistentDataStore
+ private lateinit var testLooper: TestLooper
+
+ // Devices
+ private lateinit var keyboardDevice: InputDevice
+ private lateinit var vendorSpecificKeyboardDevice: InputDevice
+ private lateinit var englishDvorakKeyboardDevice: InputDevice
+
+ @Before
+ fun setup() {
+ context = Mockito.spy(ContextWrapper(ApplicationProvider.getApplicationContext()))
+ dataStore = PersistentDataStore(object : PersistentDataStore.Injector() {
+ override fun openRead(): InputStream? {
+ throw FileNotFoundException()
+ }
+
+ override fun startWrite(): FileOutputStream? {
+ throw IOException()
+ }
+
+ override fun finishWrite(fos: FileOutputStream?, success: Boolean) {}
+ })
+ testLooper = TestLooper()
+ keyboardLayoutManager = KeyboardLayoutManager(context, native, dataStore, testLooper.looper)
+ setupInputDevices()
+ setupBroadcastReceiver()
+ setupIme()
+ }
+
+ private fun setupInputDevices() {
+ val inputManager = InputManager.resetInstance(iInputManager)
+ Mockito.`when`(context.getSystemService(Mockito.eq(Context.INPUT_SERVICE)))
+ .thenReturn(inputManager)
+
+ keyboardDevice = createKeyboard(DEVICE_ID, 0, 0, "", "")
+ vendorSpecificKeyboardDevice = createKeyboard(VENDOR_SPECIFIC_DEVICE_ID, 1, 1, "", "")
+ englishDvorakKeyboardDevice =
+ createKeyboard(ENGLISH_DVORAK_DEVICE_ID, 0, 0, "en", "dvorak")
+ Mockito.`when`(iInputManager.inputDeviceIds)
+ .thenReturn(intArrayOf(DEVICE_ID, VENDOR_SPECIFIC_DEVICE_ID, ENGLISH_DVORAK_DEVICE_ID))
+ Mockito.`when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardDevice)
+ Mockito.`when`(iInputManager.getInputDevice(VENDOR_SPECIFIC_DEVICE_ID))
+ .thenReturn(vendorSpecificKeyboardDevice)
+ Mockito.`when`(iInputManager.getInputDevice(ENGLISH_DVORAK_DEVICE_ID))
+ .thenReturn(englishDvorakKeyboardDevice)
+ }
+
+ private fun setupBroadcastReceiver() {
+ Mockito.`when`(context.packageManager).thenReturn(packageManager)
+
+ val info = createMockReceiver()
+ Mockito.`when`(packageManager.queryBroadcastReceivers(Mockito.any(), Mockito.anyInt()))
+ .thenReturn(listOf(info))
+ Mockito.`when`(packageManager.getReceiverInfo(Mockito.any(), Mockito.anyInt()))
+ .thenReturn(info.activityInfo)
+
+ val resources = context.resources
+ Mockito.`when`(
+ packageManager.getResourcesForApplication(
+ Mockito.any(
+ ApplicationInfo::class.java
+ )
+ )
+ ).thenReturn(resources)
+ }
+
+ private fun setupIme() {
+ imeInfo = InputMethodInfo(PACKAGE_NAME, RECEIVER_NAME, "", "", 0)
+ }
+
+ @Test
+ fun testDefaultUi_getKeyboardLayouts() {
+ NewSettingsApiFlag(false).use {
+ val keyboardLayouts = keyboardLayoutManager.keyboardLayouts
+ assertNotEquals(
+ "Default UI: Keyboard layout API should not return empty array",
+ 0,
+ keyboardLayouts.size
+ )
+ assertTrue(
+ "Default UI: Keyboard layout API should provide English(US) layout",
+ hasLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
+ )
+ }
+ }
+
+ @Test
+ fun testNewUi_getKeyboardLayouts() {
+ NewSettingsApiFlag(true).use {
+ val keyboardLayouts = keyboardLayoutManager.keyboardLayouts
+ assertNotEquals(
+ "New UI: Keyboard layout API should not return empty array",
+ 0,
+ keyboardLayouts.size
+ )
+ assertTrue(
+ "New UI: Keyboard layout API should provide English(US) layout",
+ hasLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
+ )
+ }
+ }
+
+ @Test
+ fun testDefaultUi_getKeyboardLayoutsForInputDevice() {
+ NewSettingsApiFlag(false).use {
+ val keyboardLayouts =
+ keyboardLayoutManager.getKeyboardLayoutsForInputDevice(keyboardDevice.identifier)
+ assertNotEquals(
+ "Default UI: getKeyboardLayoutsForInputDevice API should not return empty array",
+ 0,
+ keyboardLayouts.size
+ )
+ assertTrue(
+ "Default UI: getKeyboardLayoutsForInputDevice API should provide English(US) " +
+ "layout",
+ hasLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
+ )
+
+ val vendorSpecificKeyboardLayouts =
+ keyboardLayoutManager.getKeyboardLayoutsForInputDevice(
+ vendorSpecificKeyboardDevice.identifier
+ )
+ assertEquals(
+ "Default UI: getKeyboardLayoutsForInputDevice API should return only vendor " +
+ "specific layout",
+ 1,
+ vendorSpecificKeyboardLayouts.size
+ )
+ assertEquals(
+ "Default UI: getKeyboardLayoutsForInputDevice API should return vendor specific " +
+ "layout",
+ VENDOR_SPECIFIC_LAYOUT_DESCRIPTOR,
+ vendorSpecificKeyboardLayouts[0].descriptor
+ )
+ }
+ }
+
+ @Test
+ fun testNewUi_getKeyboardLayoutsForInputDevice() {
+ NewSettingsApiFlag(true).use {
+ val keyboardLayouts =
+ keyboardLayoutManager.getKeyboardLayoutsForInputDevice(keyboardDevice.identifier)
+ assertEquals(
+ "New UI: getKeyboardLayoutsForInputDevice API should always return empty array",
+ 0,
+ keyboardLayouts.size
+ )
+ }
+ }
+
+ @Test
+ fun testDefaultUi_getSetCurrentKeyboardLayoutForInputDevice() {
+ NewSettingsApiFlag(false).use {
+ assertNull(
+ "Default UI: getCurrentKeyboardLayoutForInputDevice API should return null if " +
+ "nothing was set",
+ keyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier
+ )
+ )
+
+ keyboardLayoutManager.setCurrentKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier,
+ ENGLISH_US_LAYOUT_DESCRIPTOR
+ )
+ val keyboardLayout =
+ keyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier
+ )
+ assertEquals(
+ "Default UI: getCurrentKeyboardLayoutForInputDevice API should return the set " +
+ "layout",
+ ENGLISH_US_LAYOUT_DESCRIPTOR,
+ keyboardLayout
+ )
+ }
+ }
+
+ @Test
+ fun testNewUi_getSetCurrentKeyboardLayoutForInputDevice() {
+ NewSettingsApiFlag(true).use {
+ keyboardLayoutManager.setCurrentKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier,
+ ENGLISH_US_LAYOUT_DESCRIPTOR
+ )
+ assertNull(
+ "New UI: getCurrentKeyboardLayoutForInputDevice API should always return null " +
+ "even after setCurrentKeyboardLayoutForInputDevice",
+ keyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier
+ )
+ )
+ }
+ }
+
+ @Test
+ fun testDefaultUi_getEnabledKeyboardLayoutsForInputDevice() {
+ NewSettingsApiFlag(false).use {
+ keyboardLayoutManager.addKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier, ENGLISH_US_LAYOUT_DESCRIPTOR
+ )
+
+ val keyboardLayouts =
+ keyboardLayoutManager.getEnabledKeyboardLayoutsForInputDevice(
+ keyboardDevice.identifier
+ )
+ assertEquals(
+ "Default UI: getEnabledKeyboardLayoutsForInputDevice API should return added " +
+ "layout",
+ 1,
+ keyboardLayouts.size
+ )
+ assertEquals(
+ "Default UI: getEnabledKeyboardLayoutsForInputDevice API should return " +
+ "English(US) layout",
+ ENGLISH_US_LAYOUT_DESCRIPTOR,
+ keyboardLayouts[0]
+ )
+ assertEquals(
+ "Default UI: getCurrentKeyboardLayoutForInputDevice API should return " +
+ "English(US) layout (Auto select the first enabled layout)",
+ ENGLISH_US_LAYOUT_DESCRIPTOR,
+ keyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier
+ )
+ )
+
+ keyboardLayoutManager.removeKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier, ENGLISH_US_LAYOUT_DESCRIPTOR
+ )
+ assertEquals(
+ "Default UI: getKeyboardLayoutsForInputDevice API should return 0 layouts",
+ 0,
+ keyboardLayoutManager.getEnabledKeyboardLayoutsForInputDevice(
+ keyboardDevice.identifier
+ ).size
+ )
+ assertNull(
+ "Default UI: getCurrentKeyboardLayoutForInputDevice API should return null after " +
+ "the enabled layout is removed",
+ keyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier
+ )
+ )
+ }
+ }
+
+ @Test
+ fun testNewUi_getEnabledKeyboardLayoutsForInputDevice() {
+ NewSettingsApiFlag(true).use {
+ keyboardLayoutManager.addKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier, ENGLISH_US_LAYOUT_DESCRIPTOR
+ )
+
+ assertEquals(
+ "New UI: getEnabledKeyboardLayoutsForInputDevice API should return always return " +
+ "an empty array",
+ 0,
+ keyboardLayoutManager.getEnabledKeyboardLayoutsForInputDevice(
+ keyboardDevice.identifier
+ ).size
+ )
+ assertNull(
+ "New UI: getCurrentKeyboardLayoutForInputDevice API should always return null",
+ keyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier
+ )
+ )
+ }
+ }
+
+ @Test
+ fun testDefaultUi_switchKeyboardLayout() {
+ NewSettingsApiFlag(false).use {
+ keyboardLayoutManager.addKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier, ENGLISH_US_LAYOUT_DESCRIPTOR
+ )
+ keyboardLayoutManager.addKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier, ENGLISH_UK_LAYOUT_DESCRIPTOR
+ )
+ assertEquals(
+ "Default UI: getCurrentKeyboardLayoutForInputDevice API should return " +
+ "English(US) layout",
+ ENGLISH_US_LAYOUT_DESCRIPTOR,
+ keyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier
+ )
+ )
+
+ keyboardLayoutManager.switchKeyboardLayout(DEVICE_ID, 1)
+
+ // Throws null pointer because trying to show toast using TestLooper
+ assertThrows(NullPointerException::class.java) { testLooper.dispatchAll() }
+ assertEquals("Default UI: getCurrentKeyboardLayoutForInputDevice API should return " +
+ "English(UK) layout",
+ ENGLISH_UK_LAYOUT_DESCRIPTOR,
+ keyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier
+ )
+ )
+ }
+ }
+
+ @Test
+ fun testNewUi_switchKeyboardLayout() {
+ NewSettingsApiFlag(true).use {
+ keyboardLayoutManager.addKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier, ENGLISH_US_LAYOUT_DESCRIPTOR
+ )
+ keyboardLayoutManager.addKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier, ENGLISH_UK_LAYOUT_DESCRIPTOR
+ )
+
+ keyboardLayoutManager.switchKeyboardLayout(DEVICE_ID, 1)
+ testLooper.dispatchAll()
+
+ assertNull("New UI: getCurrentKeyboardLayoutForInputDevice API should always return " +
+ "null",
+ keyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier
+ )
+ )
+ }
+ }
+
+ @Test
+ fun testDefaultUi_getKeyboardLayout() {
+ NewSettingsApiFlag(false).use {
+ val keyboardLayout =
+ keyboardLayoutManager.getKeyboardLayout(ENGLISH_US_LAYOUT_DESCRIPTOR)
+ assertEquals("Default UI: getKeyboardLayout API should return correct Layout from " +
+ "available layouts",
+ ENGLISH_US_LAYOUT_DESCRIPTOR,
+ keyboardLayout!!.descriptor
+ )
+ }
+ }
+
+ @Test
+ fun testNewUi_getKeyboardLayout() {
+ NewSettingsApiFlag(true).use {
+ val keyboardLayout =
+ keyboardLayoutManager.getKeyboardLayout(ENGLISH_US_LAYOUT_DESCRIPTOR)
+ assertEquals("New UI: getKeyboardLayout API should return correct Layout from " +
+ "available layouts",
+ ENGLISH_US_LAYOUT_DESCRIPTOR,
+ keyboardLayout!!.descriptor
+ )
+ }
+ }
+
+ @Test
+ fun testDefaultUi_getSetKeyboardLayoutForInputDevice_WithImeInfo() {
+ NewSettingsApiFlag(false).use {
+ val imeSubtype = createImeSubtype()
+ keyboardLayoutManager.setKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype,
+ ENGLISH_UK_LAYOUT_DESCRIPTOR
+ )
+ val keyboardLayout =
+ keyboardLayoutManager.getKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype
+ )
+ assertNull(
+ "Default UI: getKeyboardLayoutForInputDevice API should always return null",
+ keyboardLayout
+ )
+ }
+ }
+
+ @Test
+ fun testNewUi_getSetKeyboardLayoutForInputDevice_withImeInfo() {
+ NewSettingsApiFlag(true).use {
+ val imeSubtype = createImeSubtype()
+
+ keyboardLayoutManager.setKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype,
+ ENGLISH_UK_LAYOUT_DESCRIPTOR
+ )
+ assertEquals(
+ "New UI: getKeyboardLayoutForInputDevice API should return the set layout",
+ ENGLISH_UK_LAYOUT_DESCRIPTOR,
+ keyboardLayoutManager.getKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype
+ )
+ )
+
+ // This should replace previously set layout
+ keyboardLayoutManager.setKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype,
+ ENGLISH_US_LAYOUT_DESCRIPTOR
+ )
+ assertEquals(
+ "New UI: getKeyboardLayoutForInputDevice API should return the last set layout",
+ ENGLISH_US_LAYOUT_DESCRIPTOR,
+ keyboardLayoutManager.getKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype
+ )
+ )
+ }
+ }
+
+ @Test
+ fun testDefaultUi_getKeyboardLayoutListForInputDevice() {
+ NewSettingsApiFlag(false).use {
+ val keyboardLayouts =
+ keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
+ keyboardDevice.identifier, USER_ID, imeInfo,
+ createImeSubtype()
+ )
+ assertEquals("Default UI: getKeyboardLayoutListForInputDevice API should always " +
+ "return empty array",
+ 0,
+ keyboardLayouts.size
+ )
+ }
+ }
+
+ @Test
+ fun testNewUi_getKeyboardLayoutListForInputDevice() {
+ NewSettingsApiFlag(true).use {
+ // Check Layouts for "hi-Latn". It should return all 'Latn' keyboard layouts
+ var keyboardLayouts =
+ keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
+ keyboardDevice.identifier, USER_ID, imeInfo,
+ createImeSubtypeForLanguageTag("hi-Latn")
+ )
+ assertNotEquals(
+ "New UI: getKeyboardLayoutListForInputDevice API should return the list of " +
+ "supported layouts with matching script code",
+ 0,
+ keyboardLayouts.size
+ )
+
+ val englishScripts = UScript.getCode(Locale.forLanguageTag("hi-Latn"))
+ for (kl in keyboardLayouts) {
+ var isCompatible = false
+ for (i in 0 until kl.locales.size()) {
+ val locale: Locale = kl.locales.get(i) ?: continue
+ val scripts = UScript.getCode(locale)
+ if (scripts != null && areScriptsCompatible(scripts, englishScripts)) {
+ isCompatible = true
+ break
+ }
+ }
+ assertTrue(
+ "New UI: getKeyboardLayoutListForInputDevice API should only return " +
+ "compatible layouts but found " + kl.descriptor,
+ isCompatible
+ )
+ }
+
+ // Check Layouts for "hi" which by default uses 'Deva' script.
+ keyboardLayouts =
+ keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
+ keyboardDevice.identifier, USER_ID, imeInfo,
+ createImeSubtypeForLanguageTag("hi")
+ )
+ assertEquals("New UI: getKeyboardLayoutListForInputDevice API should return empty " +
+ "list if no supported layouts available",
+ 0,
+ keyboardLayouts.size
+ )
+
+ // If user manually selected some layout, always provide it in the layout list
+ val imeSubtype = createImeSubtypeForLanguageTag("hi")
+ keyboardLayoutManager.setKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype,
+ ENGLISH_US_LAYOUT_DESCRIPTOR
+ )
+ keyboardLayouts =
+ keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
+ keyboardDevice.identifier, USER_ID, imeInfo,
+ imeSubtype
+ )
+ assertEquals("New UI: getKeyboardLayoutListForInputDevice API should return user " +
+ "selected layout even if the script is incompatible with IME",
+ 1,
+ keyboardLayouts.size
+ )
+ }
+ }
+
+ @Test
+ fun testNewUi_getDefaultKeyboardLayoutForInputDevice_withImeLanguageTag() {
+ NewSettingsApiFlag(true).use {
+ assertCorrectLayout(
+ keyboardDevice,
+ createImeSubtypeForLanguageTag("en-US"),
+ ENGLISH_US_LAYOUT_DESCRIPTOR
+ )
+ assertCorrectLayout(
+ keyboardDevice,
+ createImeSubtypeForLanguageTag("en-GB"),
+ ENGLISH_UK_LAYOUT_DESCRIPTOR
+ )
+ assertCorrectLayout(
+ keyboardDevice,
+ createImeSubtypeForLanguageTag("de"),
+ createLayoutDescriptor("keyboard_layout_german")
+ )
+ assertCorrectLayout(
+ keyboardDevice,
+ createImeSubtypeForLanguageTag("fr-FR"),
+ createLayoutDescriptor("keyboard_layout_french")
+ )
+ assertCorrectLayout(
+ keyboardDevice,
+ createImeSubtypeForLanguageTag("ru"),
+ createLayoutDescriptor("keyboard_layout_russian")
+ )
+ assertNull(
+ "New UI: getDefaultKeyboardLayoutForInputDevice should return null when no " +
+ "layout available",
+ keyboardLayoutManager.getKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier, USER_ID, imeInfo,
+ createImeSubtypeForLanguageTag("it")
+ )
+ )
+ assertNull(
+ "New UI: getDefaultKeyboardLayoutForInputDevice should return null when no " +
+ "layout for script code is available",
+ keyboardLayoutManager.getKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier, USER_ID, imeInfo,
+ createImeSubtypeForLanguageTag("en-Deva")
+ )
+ )
+ }
+ }
+
+ @Test
+ fun testNewUi_getDefaultKeyboardLayoutForInputDevice_withImeLanguageTagAndLayoutType() {
+ NewSettingsApiFlag(true).use {
+ assertCorrectLayout(
+ keyboardDevice,
+ createImeSubtypeForLanguageTagAndLayoutType("en-US", "qwerty"),
+ ENGLISH_US_LAYOUT_DESCRIPTOR
+ )
+ assertCorrectLayout(
+ keyboardDevice,
+ createImeSubtypeForLanguageTagAndLayoutType("en-US", "dvorak"),
+ createLayoutDescriptor("keyboard_layout_english_us_dvorak")
+ )
+ // Try to match layout type even if country doesn't match
+ assertCorrectLayout(
+ keyboardDevice,
+ createImeSubtypeForLanguageTagAndLayoutType("en-GB", "dvorak"),
+ createLayoutDescriptor("keyboard_layout_english_us_dvorak")
+ )
+ // Choose layout based on layout type priority, if layout type is not provided by IME
+ // (Qwerty > Dvorak > Extended)
+ assertCorrectLayout(
+ keyboardDevice,
+ createImeSubtypeForLanguageTagAndLayoutType("en-US", ""),
+ ENGLISH_US_LAYOUT_DESCRIPTOR
+ )
+ assertCorrectLayout(
+ keyboardDevice,
+ createImeSubtypeForLanguageTagAndLayoutType("en-GB", "qwerty"),
+ ENGLISH_UK_LAYOUT_DESCRIPTOR
+ )
+ assertCorrectLayout(
+ keyboardDevice,
+ createImeSubtypeForLanguageTagAndLayoutType("de", "qwertz"),
+ createLayoutDescriptor("keyboard_layout_german")
+ )
+ // Wrong layout type should match with language if provided layout type not available
+ assertCorrectLayout(
+ keyboardDevice,
+ createImeSubtypeForLanguageTagAndLayoutType("de", "qwerty"),
+ createLayoutDescriptor("keyboard_layout_german")
+ )
+ assertCorrectLayout(
+ keyboardDevice,
+ createImeSubtypeForLanguageTagAndLayoutType("fr-FR", "azerty"),
+ createLayoutDescriptor("keyboard_layout_french")
+ )
+ assertCorrectLayout(
+ keyboardDevice,
+ createImeSubtypeForLanguageTagAndLayoutType("ru", "qwerty"),
+ createLayoutDescriptor("keyboard_layout_russian_qwerty")
+ )
+ // If layout type is empty then prioritize KCM with empty layout type
+ assertCorrectLayout(
+ keyboardDevice,
+ createImeSubtypeForLanguageTagAndLayoutType("ru", ""),
+ createLayoutDescriptor("keyboard_layout_russian")
+ )
+ assertNull("New UI: getDefaultKeyboardLayoutForInputDevice should return null when " +
+ "no layout for script code is available",
+ keyboardLayoutManager.getKeyboardLayoutForInputDevice(
+ keyboardDevice.identifier, USER_ID, imeInfo,
+ createImeSubtypeForLanguageTagAndLayoutType("en-Deva-US", "")
+ )
+ )
+ }
+ }
+
+ @Test
+ fun testNewUi_getDefaultKeyboardLayoutForInputDevice_withHwLanguageTagAndLayoutType() {
+ NewSettingsApiFlag(true).use {
+ // Should return English dvorak even if IME current layout is qwerty, since HW says the
+ // keyboard is a Dvorak keyboard
+ assertCorrectLayout(
+ englishDvorakKeyboardDevice,
+ createImeSubtypeForLanguageTagAndLayoutType("en", "qwerty"),
+ createLayoutDescriptor("keyboard_layout_english_us_dvorak")
+ )
+
+ // Fallback to IME information if the HW provided layout script is incompatible with the
+ // provided IME subtype
+ assertCorrectLayout(
+ englishDvorakKeyboardDevice,
+ createImeSubtypeForLanguageTagAndLayoutType("ru", ""),
+ createLayoutDescriptor("keyboard_layout_russian")
+ )
+ }
+ }
+
+ private fun assertCorrectLayout(
+ device: InputDevice,
+ imeSubtype: InputMethodSubtype,
+ expectedLayout: String
+ ) {
+ assertEquals(
+ "New UI: getDefaultKeyboardLayoutForInputDevice should return $expectedLayout",
+ expectedLayout,
+ keyboardLayoutManager.getKeyboardLayoutForInputDevice(
+ device.identifier, USER_ID, imeInfo, imeSubtype
+ )
+ )
+ }
+
+ private fun createImeSubtype(): InputMethodSubtype =
+ InputMethodSubtype.InputMethodSubtypeBuilder().setSubtypeId(nextImeSubtypeId++).build()
+
+ private fun createImeSubtypeForLanguageTag(languageTag: String): InputMethodSubtype =
+ InputMethodSubtype.InputMethodSubtypeBuilder().setSubtypeId(nextImeSubtypeId++)
+ .setLanguageTag(languageTag).build()
+
+ private fun createImeSubtypeForLanguageTagAndLayoutType(
+ languageTag: String,
+ layoutType: String
+ ): InputMethodSubtype =
+ InputMethodSubtype.InputMethodSubtypeBuilder().setSubtypeId(nextImeSubtypeId++)
+ .setPhysicalKeyboardHint(ULocale.forLanguageTag(languageTag), layoutType).build()
+
+ private fun hasLayout(layoutList: Array<KeyboardLayout>, layoutDesc: String): Boolean {
+ for (kl in layoutList) {
+ if (kl.descriptor == layoutDesc) {
+ return true
+ }
+ }
+ return false
+ }
+
+ private fun createLayoutDescriptor(keyboardName: String): String =
+ "$PACKAGE_NAME/$RECEIVER_NAME/$keyboardName"
+
+ private fun areScriptsCompatible(scriptList1: IntArray, scriptList2: IntArray): Boolean {
+ for (s1 in scriptList1) {
+ for (s2 in scriptList2) {
+ if (s1 == s2) return true
+ }
+ }
+ return false
+ }
+
+ private fun createMockReceiver(): ResolveInfo {
+ val info = ResolveInfo()
+ info.activityInfo = ActivityInfo()
+ info.activityInfo.packageName = PACKAGE_NAME
+ info.activityInfo.name = RECEIVER_NAME
+ info.activityInfo.applicationInfo = ApplicationInfo()
+ info.activityInfo.metaData = Bundle()
+ info.activityInfo.metaData.putInt(
+ InputManager.META_DATA_KEYBOARD_LAYOUTS,
+ R.xml.keyboard_layouts
+ )
+ info.serviceInfo = ServiceInfo()
+ info.serviceInfo.packageName = PACKAGE_NAME
+ info.serviceInfo.name = RECEIVER_NAME
+ return info
+ }
+
+ private inner class NewSettingsApiFlag constructor(enabled: Boolean) : AutoCloseable {
+ init {
+ Settings.Global.putString(
+ context.contentResolver,
+ "settings_new_keyboard_ui", enabled.toString()
+ )
+ }
+
+ override fun close() {
+ Settings.Global.putString(
+ context.contentResolver,
+ "settings_new_keyboard_ui",
+ ""
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/job/BackgroundRestrictionsTest.java b/services/tests/servicestests/src/com/android/server/job/BackgroundRestrictionsTest.java
index f5029ec..f2e03aa 100644
--- a/services/tests/servicestests/src/com/android/server/job/BackgroundRestrictionsTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/BackgroundRestrictionsTest.java
@@ -165,6 +165,7 @@
awaitJobStart(DEFAULT_WAIT_TIMEOUT));
}
+ @FlakyTest
@Test
public void testFeatureFlag() throws Exception {
Settings.Global.putInt(mContext.getContentResolver(),
diff --git a/services/tests/servicestests/src/com/android/server/job/BiasSchedulingTest.java b/services/tests/servicestests/src/com/android/server/job/BiasSchedulingTest.java
index e886e7d..56d01b0 100644
--- a/services/tests/servicestests/src/com/android/server/job/BiasSchedulingTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/BiasSchedulingTest.java
@@ -57,14 +57,14 @@
}
public void testLowerBiasJobPreempted() throws Exception {
- for (int i = 0; i < JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT; ++i) {
+ for (int i = 0; i < JobConcurrencyManager.MAX_CONCURRENCY_LIMIT; ++i) {
JobInfo job = new JobInfo.Builder(100 + i, sJobServiceComponent)
.setBias(LOW_BIAS)
.setOverrideDeadline(0)
.build();
mJobScheduler.schedule(job);
}
- final int higherBiasJobId = 100 + JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT;
+ final int higherBiasJobId = 100 + JobConcurrencyManager.MAX_CONCURRENCY_LIMIT;
JobInfo jobHigher = new JobInfo.Builder(higherBiasJobId, sJobServiceComponent)
.setBias(HIGH_BIAS)
.setMinimumLatency(2000)
@@ -88,14 +88,14 @@
}
public void testHigherBiasJobNotPreempted() throws Exception {
- for (int i = 0; i < JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT; ++i) {
+ for (int i = 0; i < JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT; ++i) {
JobInfo job = new JobInfo.Builder(100 + i, sJobServiceComponent)
.setBias(HIGH_BIAS)
.setOverrideDeadline(0)
.build();
mJobScheduler.schedule(job);
}
- final int lowerBiasJobId = 100 + JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT;
+ final int lowerBiasJobId = 100 + JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT;
JobInfo jobLower = new JobInfo.Builder(lowerBiasJobId, sJobServiceComponent)
.setBias(LOW_BIAS)
.setMinimumLatency(2000)
diff --git a/services/tests/servicestests/src/com/android/server/job/WorkCountTrackerTest.java b/services/tests/servicestests/src/com/android/server/job/WorkCountTrackerTest.java
index dd9ae65..0fd6a9e 100644
--- a/services/tests/servicestests/src/com/android/server/job/WorkCountTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/WorkCountTrackerTest.java
@@ -16,6 +16,7 @@
package com.android.server.job;
+import static com.android.server.job.JobConcurrencyManager.MAX_CONCURRENCY_LIMIT;
import static com.android.server.job.JobConcurrencyManager.NUM_WORK_TYPES;
import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_BG;
import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_BGUSER;
@@ -191,10 +192,10 @@
}
private void recount(Jobs jobs, int totalMax,
- @NonNull List<Pair<Integer, Integer>> minLimits,
- @NonNull List<Pair<Integer, Integer>> maxLimits) {
+ @NonNull List<Pair<Integer, Float>> minLimitRatios,
+ @NonNull List<Pair<Integer, Float>> maxLimitRatios) {
mWorkCountTracker.setConfig(new JobConcurrencyManager.WorkTypeConfig(
- "test", totalMax, minLimits, maxLimits));
+ "test", MAX_CONCURRENCY_LIMIT, totalMax, minLimitRatios, maxLimitRatios));
mWorkCountTracker.resetCounts();
for (int i = 0; i < jobs.running.size(); ++i) {
@@ -259,18 +260,18 @@
* Used by the following testRandom* tests.
*/
private void checkRandom(Jobs jobs, int numTests, int totalMax,
- @NonNull List<Pair<Integer, Integer>> minLimits,
- @NonNull List<Pair<Integer, Integer>> maxLimits,
+ @NonNull List<Pair<Integer, Float>> minLimitRatios,
+ @NonNull List<Pair<Integer, Float>> maxLimitRatios,
double probStart, double[] typeCdf, double[] numTypesCdf, double probStop) {
int minExpected = 0;
- for (Pair<Integer, Integer> minLimit : minLimits) {
- minExpected = Math.min(minLimit.second, minExpected);
+ for (Pair<Integer, Float> minLimit : minLimitRatios) {
+ minExpected = Math.min((int) (minLimit.second * MAX_CONCURRENCY_LIMIT), minExpected);
}
for (int i = 0; i < numTests; i++) {
jobs.maybeFinishJobs(probStop);
jobs.maybeEnqueueJobs(probStart, typeCdf, numTypesCdf);
- recount(jobs, totalMax, minLimits, maxLimits);
+ recount(jobs, totalMax, minLimitRatios, maxLimitRatios);
final int numPending = jobs.pendingMultiTypes.size();
startPendingJobs(jobs);
@@ -284,9 +285,11 @@
}
assertThat(totalRunning).isAtMost(totalMax);
assertThat(totalRunning).isAtLeast(Math.min(minExpected, numPending));
- for (Pair<Integer, Integer> maxLimit : maxLimits) {
- assertWithMessage("Work type " + maxLimit.first + " is running too many jobs")
- .that(jobs.running.get(maxLimit.first)).isAtMost(maxLimit.second);
+ for (Pair<Integer, Float> maxLimitRatio : maxLimitRatios) {
+ final int workType = maxLimitRatio.first;
+ final int maxLimit = (int) (maxLimitRatio.second * MAX_CONCURRENCY_LIMIT);
+ assertWithMessage("Work type " + workType + " is running too many jobs")
+ .that(jobs.running.get(workType)).isAtMost(maxLimit);
}
}
}
@@ -302,12 +305,14 @@
final int numTests = 5000;
final int totalMax = 6;
- final List<Pair<Integer, Integer>> maxLimits = List.of(Pair.create(WORK_TYPE_BG, 4));
- final List<Pair<Integer, Integer>> minLimits = List.of(Pair.create(WORK_TYPE_BG, 2));
+ final List<Pair<Integer, Float>> minLimitRatios =
+ List.of(Pair.create(WORK_TYPE_BG, 1.0f / 3));
+ final List<Pair<Integer, Float>> maxLimitRatios =
+ List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3));
final double probStop = 0.1;
final double probStart = 0.1;
- checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart,
+ checkRandom(jobs, numTests, totalMax, minLimitRatios, maxLimitRatios, probStart,
EQUAL_PROBABILITY_CDF, EQUAL_PROBABILITY_CDF, probStop);
}
@@ -317,15 +322,15 @@
final int numTests = 5000;
final int totalMax = 2;
- final List<Pair<Integer, Integer>> maxLimits =
- List.of(Pair.create(WORK_TYPE_BG, 2), Pair.create(WORK_TYPE_BGUSER, 1));
- final List<Pair<Integer, Integer>> minLimits = List.of();
+ final List<Pair<Integer, Float>> minLimitRatios = List.of();
+ final List<Pair<Integer, Float>> maxLimitRatios =
+ List.of(Pair.create(WORK_TYPE_BG, 1f), Pair.create(WORK_TYPE_BGUSER, .5f));
final double probStop = 0.5;
final double[] cdf = buildWorkTypeCdf(0.5, 0, 0, 0.5, 0, 0);
final double[] numTypesCdf = buildCdf(.5, .3, .15, .05);
final double probStart = 0.5;
- checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart,
+ checkRandom(jobs, numTests, totalMax, minLimitRatios, maxLimitRatios, probStart,
cdf, numTypesCdf, probStop);
}
@@ -335,15 +340,15 @@
final int numTests = 5000;
final int totalMax = 2;
- final List<Pair<Integer, Integer>> maxLimits =
- List.of(Pair.create(WORK_TYPE_BG, 2), Pair.create(WORK_TYPE_BGUSER, 1));
- final List<Pair<Integer, Integer>> minLimits = List.of(Pair.create(WORK_TYPE_BG, 2));
+ final List<Pair<Integer, Float>> minLimitRatios = List.of(Pair.create(WORK_TYPE_BG, .99f));
+ final List<Pair<Integer, Float>> maxLimitRatios =
+ List.of(Pair.create(WORK_TYPE_BG, 1f), Pair.create(WORK_TYPE_BGUSER, .5f));
final double probStop = 0.5;
final double[] cdf = buildWorkTypeCdf(1.0 / 3, 0, 0, 1.0 / 3, 0, 1.0 / 3);
final double[] numTypesCdf = buildCdf(.75, .2, .05);
final double probStart = 0.5;
- checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart,
+ checkRandom(jobs, numTests, totalMax, minLimitRatios, maxLimitRatios, probStart,
cdf, numTypesCdf, probStop);
}
@@ -353,15 +358,15 @@
final int numTests = 5000;
final int totalMax = 10;
- final List<Pair<Integer, Integer>> maxLimits =
- List.of(Pair.create(WORK_TYPE_BG, 2), Pair.create(WORK_TYPE_BGUSER, 1));
- final List<Pair<Integer, Integer>> minLimits = List.of();
+ final List<Pair<Integer, Float>> minLimitRatios = List.of();
+ final List<Pair<Integer, Float>> maxLimitRatios =
+ List.of(Pair.create(WORK_TYPE_BG, .2f), Pair.create(WORK_TYPE_BGUSER, .1f));
final double probStop = 0.5;
final double[] cdf = buildWorkTypeCdf(1.0 / 3, 0, 0, 1.0 / 3, 0, 1.0 / 3);
final double[] numTypesCdf = buildCdf(.05, .95);
final double probStart = 0.5;
- checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart,
+ checkRandom(jobs, numTests, totalMax, minLimitRatios, maxLimitRatios, probStart,
cdf, numTypesCdf, probStop);
}
@@ -371,15 +376,17 @@
final int numTests = 5000;
final int totalMax = 6;
- final List<Pair<Integer, Integer>> maxLimits =
- List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 2));
- final List<Pair<Integer, Integer>> minLimits = List.of(Pair.create(WORK_TYPE_BG, 2));
+ final List<Pair<Integer, Float>> minLimitRatios =
+ List.of(Pair.create(WORK_TYPE_BG, 1.0f / 3));
+ final List<Pair<Integer, Float>> maxLimitRatios =
+ List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3),
+ Pair.create(WORK_TYPE_BGUSER, 2.0f / 3));
final double probStop = 0.5;
final double[] cdf = buildWorkTypeCdf(0.1, 0, 0, 0.8, 0.02, .08);
final double[] numTypesCdf = buildCdf(.5, .3, .15, .05);
final double probStart = 0.5;
- checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart,
+ checkRandom(jobs, numTests, totalMax, minLimitRatios, maxLimitRatios, probStart,
cdf, numTypesCdf, probStop);
}
@@ -389,15 +396,17 @@
final int numTests = 5000;
final int totalMax = 6;
- final List<Pair<Integer, Integer>> maxLimits =
- List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 2));
- final List<Pair<Integer, Integer>> minLimits = List.of(Pair.create(WORK_TYPE_BG, 2));
+ final List<Pair<Integer, Float>> minLimitRatios =
+ List.of(Pair.create(WORK_TYPE_BG, 1.0f / 3));
+ final List<Pair<Integer, Float>> maxLimitRatios =
+ List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3),
+ Pair.create(WORK_TYPE_BGUSER, 1.0f / 3));
final double probStop = 0.5;
final double[] cdf = buildWorkTypeCdf(0.85, 0.05, 0, 0.1, 0, 0);
final double[] numTypesCdf = buildCdf(1);
final double probStart = 0.5;
- checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart,
+ checkRandom(jobs, numTests, totalMax, minLimitRatios, maxLimitRatios, probStart,
cdf, numTypesCdf, probStop);
}
@@ -407,15 +416,17 @@
final int numTests = 5000;
final int totalMax = 6;
- final List<Pair<Integer, Integer>> maxLimits =
- List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 2));
- final List<Pair<Integer, Integer>> minLimits = List.of(Pair.create(WORK_TYPE_BG, 2));
+ final List<Pair<Integer, Float>> minLimitRatios =
+ List.of(Pair.create(WORK_TYPE_BG, 1.0f / 3));
+ final List<Pair<Integer, Float>> maxLimitRatios =
+ List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3),
+ Pair.create(WORK_TYPE_BGUSER, 1.0f / 3));
final double probStop = 0.4;
final double[] cdf = buildWorkTypeCdf(0.1, 0, 0, 0.1, 0.05, .75);
final double[] numTypesCdf = buildCdf(0.5, 0.5);
final double probStart = 0.5;
- checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart,
+ checkRandom(jobs, numTests, totalMax, minLimitRatios, maxLimitRatios, probStart,
cdf, numTypesCdf, probStop);
}
@@ -425,16 +436,18 @@
final int numTests = 5000;
final int totalMax = 6;
- final List<Pair<Integer, Integer>> maxLimits =
- List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 2));
- final List<Pair<Integer, Integer>> minLimits =
- List.of(Pair.create(WORK_TYPE_BG, 2), Pair.create(WORK_TYPE_BGUSER, 1));
+ final List<Pair<Integer, Float>> minLimitRatios =
+ List.of(Pair.create(WORK_TYPE_BG, 1.0f / 3),
+ Pair.create(WORK_TYPE_BGUSER, 1.0f / 6));
+ final List<Pair<Integer, Float>> maxLimitRatios =
+ List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3),
+ Pair.create(WORK_TYPE_BGUSER, 1.0f / 3));
final double probStop = 0.4;
final double[] cdf = buildWorkTypeCdf(0.8, 0.1, 0, 0.05, 0, 0.05);
final double[] numTypesCdf = buildCdf(1);
final double probStart = 0.5;
- checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart,
+ checkRandom(jobs, numTests, totalMax, minLimitRatios, maxLimitRatios, probStart,
cdf, numTypesCdf, probStop);
}
@@ -444,16 +457,18 @@
final int numTests = 5000;
final int totalMax = 6;
- final List<Pair<Integer, Integer>> maxLimits =
- List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 2));
- final List<Pair<Integer, Integer>> minLimits =
- List.of(Pair.create(WORK_TYPE_BG, 2), Pair.create(WORK_TYPE_BGUSER, 1));
+ final List<Pair<Integer, Float>> minLimitRatios =
+ List.of(Pair.create(WORK_TYPE_BG, 1.0f / 3),
+ Pair.create(WORK_TYPE_BGUSER, 1.0f / 6));
+ final List<Pair<Integer, Float>> maxLimitRatios =
+ List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3),
+ Pair.create(WORK_TYPE_BGUSER, 1.0f / 3));
final double probStop = 0.5;
final double[] cdf = buildWorkTypeCdf(0, 0, 0, 0.5, 0, 0.5);
final double[] numTypesCdf = buildCdf(1);
final double probStart = 0.5;
- checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart,
+ checkRandom(jobs, numTests, totalMax, minLimitRatios, maxLimitRatios, probStart,
cdf, numTypesCdf, probStop);
}
@@ -463,16 +478,18 @@
final int numTests = 5000;
final int totalMax = 6;
- final List<Pair<Integer, Integer>> maxLimits =
- List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 2));
- final List<Pair<Integer, Integer>> minLimits =
- List.of(Pair.create(WORK_TYPE_BG, 2), Pair.create(WORK_TYPE_BGUSER, 1));
+ final List<Pair<Integer, Float>> minLimitRatios =
+ List.of(Pair.create(WORK_TYPE_BG, 1.0f / 3),
+ Pair.create(WORK_TYPE_BGUSER, 1.0f / 6));
+ final List<Pair<Integer, Float>> maxLimitRatios =
+ List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3),
+ Pair.create(WORK_TYPE_BGUSER, 1.0f / 3));
final double probStop = 0.5;
final double[] cdf = buildWorkTypeCdf(0, 0, 0, 0.1, 0, 0.9);
final double[] numTypesCdf = buildCdf(0.9, 0.1);
final double probStart = 0.5;
- checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart,
+ checkRandom(jobs, numTests, totalMax, minLimitRatios, maxLimitRatios, probStart,
cdf, numTypesCdf, probStop);
}
@@ -482,16 +499,18 @@
final int numTests = 5000;
final int totalMax = 6;
- final List<Pair<Integer, Integer>> maxLimits =
- List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 2));
- final List<Pair<Integer, Integer>> minLimits =
- List.of(Pair.create(WORK_TYPE_BG, 2), Pair.create(WORK_TYPE_BGUSER, 1));
+ final List<Pair<Integer, Float>> minLimitRatios =
+ List.of(Pair.create(WORK_TYPE_BG, 1.0f / 3),
+ Pair.create(WORK_TYPE_BGUSER, 1.0f / 6));
+ final List<Pair<Integer, Float>> maxLimitRatios =
+ List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3),
+ Pair.create(WORK_TYPE_BGUSER, 1.0f / 3));
final double probStop = 0.5;
final double[] cdf = buildWorkTypeCdf(0, 0, 0, 0.9, 0, 0.1);
final double[] numTypesCdf = buildCdf(1);
final double probStart = 0.5;
- checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart,
+ checkRandom(jobs, numTests, totalMax, minLimitRatios, maxLimitRatios, probStart,
cdf, numTypesCdf, probStop);
}
@@ -501,15 +520,16 @@
final int numTests = 5000;
final int totalMax = 6;
- final List<Pair<Integer, Integer>> maxLimits = List.of(Pair.create(WORK_TYPE_BG, 4));
- final List<Pair<Integer, Integer>> minLimits =
- List.of(Pair.create(WORK_TYPE_EJ, 2), Pair.create(WORK_TYPE_BG, 2));
+ final List<Pair<Integer, Float>> minLimitRatios =
+ List.of(Pair.create(WORK_TYPE_EJ, 1.0f / 3), Pair.create(WORK_TYPE_BG, 1.0f / 3));
+ final List<Pair<Integer, Float>> maxLimitRatios =
+ List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3));
final double probStop = 0.4;
final double[] cdf = buildWorkTypeCdf(0.5, 0, 0.5, 0, 0, 0);
final double[] numTypesCdf = buildCdf(0.1, 0.7, 0.2);
final double probStart = 0.5;
- checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart,
+ checkRandom(jobs, numTests, totalMax, minLimitRatios, maxLimitRatios, probStart,
cdf, numTypesCdf, probStop);
}
@@ -522,16 +542,16 @@
final int numTests = 5000;
final int totalMax = 13;
- final List<Pair<Integer, Integer>> maxLimits = List.of(
- Pair.create(WORK_TYPE_EJ, 5), Pair.create(WORK_TYPE_BG, 4),
- Pair.create(WORK_TYPE_BGUSER, 3));
- final List<Pair<Integer, Integer>> minLimits =
- List.of(Pair.create(WORK_TYPE_EJ, 2), Pair.create(WORK_TYPE_BG, 1));
+ final List<Pair<Integer, Float>> minLimitRatios =
+ List.of(Pair.create(WORK_TYPE_EJ, 2.0f / 13), Pair.create(WORK_TYPE_BG, 1.0f / 13));
+ final List<Pair<Integer, Float>> maxLimitRatios = List.of(
+ Pair.create(WORK_TYPE_EJ, 5.0f / 13), Pair.create(WORK_TYPE_BG, 4.0f / 13),
+ Pair.create(WORK_TYPE_BGUSER, 3.0f / 13));
final double probStop = 0.13;
final double[] numTypesCdf = buildCdf(0, 0.05, 0.1, 0.7, 0.1, 0.05);
final double probStart = 0.87;
- checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart,
+ checkRandom(jobs, numTests, totalMax, minLimitRatios, maxLimitRatios, probStart,
EQUAL_PROBABILITY_CDF, numTypesCdf, probStop);
}
@@ -541,15 +561,16 @@
final int numTests = 5000;
final int totalMax = 6;
- final List<Pair<Integer, Integer>> maxLimits =
- List.of(Pair.create(WORK_TYPE_EJ, 5), Pair.create(WORK_TYPE_BG, 4));
- final List<Pair<Integer, Integer>> minLimits = List.of(Pair.create(WORK_TYPE_BG, 2));
+ final List<Pair<Integer, Float>> minLimitRatios =
+ List.of(Pair.create(WORK_TYPE_BG, 1.0f / 3));
+ final List<Pair<Integer, Float>> maxLimitRatios =
+ List.of(Pair.create(WORK_TYPE_EJ, 5.0f / 6), Pair.create(WORK_TYPE_BG, 2.0f / 3));
final double probStop = 0.4;
final double[] cdf = buildWorkTypeCdf(.1, 0, 0.5, 0.35, 0, 0.05);
final double[] numTypesCdf = buildCdf(1);
final double probStart = 0.5;
- checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart,
+ checkRandom(jobs, numTests, totalMax, minLimitRatios, maxLimitRatios, probStart,
cdf, numTypesCdf, probStop);
}
@@ -559,17 +580,17 @@
final int numTests = 5000;
final int totalMax = 6;
- final List<Pair<Integer, Integer>> maxLimits =
- List.of(Pair.create(WORK_TYPE_EJ, 5), Pair.create(WORK_TYPE_BG, 4),
- Pair.create(WORK_TYPE_BGUSER, 1));
- final List<Pair<Integer, Integer>> minLimits =
- List.of(Pair.create(WORK_TYPE_EJ, 3), Pair.create(WORK_TYPE_BG, 2));
+ final List<Pair<Integer, Float>> minLimitRatios =
+ List.of(Pair.create(WORK_TYPE_EJ, .5f), Pair.create(WORK_TYPE_BG, 1.0f / 3));
+ final List<Pair<Integer, Float>> maxLimitRatios =
+ List.of(Pair.create(WORK_TYPE_EJ, 5.0f / 6), Pair.create(WORK_TYPE_BG, 2.0f / 3),
+ Pair.create(WORK_TYPE_BGUSER, 1.0f / 6));
final double probStop = 0.4;
final double[] cdf = buildWorkTypeCdf(0.01, 0.09, 0.4, 0.1, 0, 0.4);
final double[] numTypesCdf = buildCdf(0.7, 0.3);
final double probStart = 0.5;
- checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart,
+ checkRandom(jobs, numTests, totalMax, minLimitRatios, maxLimitRatios, probStart,
cdf, numTypesCdf, probStop);
}
@@ -579,25 +600,25 @@
final int numTests = 5000;
final int totalMax = 7;
- final List<Pair<Integer, Integer>> maxLimits =
- List.of(Pair.create(WORK_TYPE_EJ, 5), Pair.create(WORK_TYPE_BG, 4),
- Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1),
- Pair.create(WORK_TYPE_BGUSER, 1));
- final List<Pair<Integer, Integer>> minLimits =
- List.of(Pair.create(WORK_TYPE_EJ, 3), Pair.create(WORK_TYPE_BG, 2));
+ final List<Pair<Integer, Float>> minLimitRatios =
+ List.of(Pair.create(WORK_TYPE_EJ, 3.0f / 7), Pair.create(WORK_TYPE_BG, 2.0f / 7));
+ final List<Pair<Integer, Float>> maxLimitRatios =
+ List.of(Pair.create(WORK_TYPE_EJ, 5.0f / 7), Pair.create(WORK_TYPE_BG, 4.0f / 7),
+ Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1.0f / 7),
+ Pair.create(WORK_TYPE_BGUSER, 1.0f / 7));
final double probStop = 0.4;
final double[] cdf = buildWorkTypeCdf(0.01, 0.09, 0.25, 0.05, 0.3, 0.3);
final double[] numTypesCdf = buildCdf(0.7, 0.3);
final double probStart = 0.5;
- checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart,
+ checkRandom(jobs, numTests, totalMax, minLimitRatios, maxLimitRatios, probStart,
cdf, numTypesCdf, probStop);
}
/** Used by the following tests */
private void checkSimple(int totalMax,
- @NonNull List<Pair<Integer, Integer>> minLimits,
- @NonNull List<Pair<Integer, Integer>> maxLimits,
+ @NonNull List<Pair<Integer, Float>> minLimitRatios,
+ @NonNull List<Pair<Integer, Float>> maxLimitRatios,
@NonNull List<Pair<Integer, Integer>> running,
@NonNull List<Pair<Integer, Integer>> pending,
@NonNull List<Pair<Integer, Integer>> resultRunning,
@@ -610,17 +631,19 @@
jobs.addPending(pend.first, pend.second);
}
- recount(jobs, totalMax, minLimits, maxLimits);
+ recount(jobs, totalMax, minLimitRatios, maxLimitRatios);
startPendingJobs(jobs);
for (Pair<Integer, Integer> run : resultRunning) {
assertWithMessage(
- "Incorrect running result for work type " + workTypeToString(run.first))
+ "Incorrect running result for work type " + workTypeToString(run.first)
+ + " wanted " + run.second + ", got " + jobs.running.get(run.first))
.that(jobs.running.get(run.first)).isEqualTo(run.second);
}
for (Pair<Integer, Integer> pend : resultPending) {
assertWithMessage(
- "Incorrect pending result for work type " + workTypeToString(pend.first))
+ "Incorrect pending result for work type " + workTypeToString(pend.first)
+ + " wanted " + pend.second + ", got " + jobs.pending.get(pend.first))
.that(jobs.pending.get(pend.first)).isEqualTo(pend.second);
}
}
@@ -628,16 +651,18 @@
@Test
public void testBasic() {
checkSimple(6,
- /* min */ List.of(Pair.create(WORK_TYPE_BG, 2)),
- /* max */ List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 2)),
+ /* min */ List.of(Pair.create(WORK_TYPE_BG, 1.0f / 3)),
+ /* max */List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3),
+ Pair.create(WORK_TYPE_BGUSER, 1.0f / 3)),
/* run */ List.of(),
/* pen */ List.of(Pair.create(WORK_TYPE_TOP, 1)),
/* resRun */ List.of(Pair.create(WORK_TYPE_TOP, 1)),
/* resPen */ List.of());
checkSimple(6,
- /* min */ List.of(Pair.create(WORK_TYPE_BG, 2)),
- /* max */ List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 2)),
+ /* min */ List.of(Pair.create(WORK_TYPE_BG, 1.0f / 3)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3),
+ Pair.create(WORK_TYPE_BGUSER, 1.0f / 3)),
/* run */ List.of(),
/* pen */ List.of(Pair.create(WORK_TYPE_TOP, 10)),
/* resRun */ List.of(Pair.create(WORK_TYPE_TOP, 6)),
@@ -645,39 +670,40 @@
// When there are BG jobs pending, 2 (min-BG) jobs should run.
checkSimple(6,
- /* min */ List.of(Pair.create(WORK_TYPE_BG, 2)),
- /* max */ List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 2)),
+ /* min */ List.of(Pair.create(WORK_TYPE_BG, 1.0f / 3)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3),
+ Pair.create(WORK_TYPE_BGUSER, 1.0f / 3)),
/* run */ List.of(),
/* pen */ List.of(Pair.create(WORK_TYPE_TOP, 10), Pair.create(WORK_TYPE_BG, 1)),
/* resRun */ List.of(Pair.create(WORK_TYPE_TOP, 5), Pair.create(WORK_TYPE_BG, 1)),
/* resPen */ List.of(Pair.create(WORK_TYPE_TOP, 5)));
checkSimple(6,
- /* min */ List.of(Pair.create(WORK_TYPE_BG, 2)),
- /* max */ List.of(Pair.create(WORK_TYPE_BG, 4)),
+ /* min */ List.of(Pair.create(WORK_TYPE_BG, 1.0f / 3)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3)),
/* run */ List.of(),
/* pen */ List.of(Pair.create(WORK_TYPE_TOP, 10), Pair.create(WORK_TYPE_BG, 3)),
/* resRun */ List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_BG, 2)),
/* resPen */ List.of(Pair.create(WORK_TYPE_TOP, 6), Pair.create(WORK_TYPE_BG, 1)));
checkSimple(8,
- /* min */ List.of(Pair.create(WORK_TYPE_BG, 2)),
- /* max */ List.of(Pair.create(WORK_TYPE_BG, 6)),
+ /* min */ List.of(Pair.create(WORK_TYPE_BG, .25f)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, .75f)),
/* run */ List.of(),
/* pen */ List.of(Pair.create(WORK_TYPE_BG, 49)),
/* resRun */ List.of(Pair.create(WORK_TYPE_BG, 6)),
/* resPen */ List.of(Pair.create(WORK_TYPE_BG, 43)));
checkSimple(8,
- /* min */ List.of(Pair.create(WORK_TYPE_BG, 2)),
- /* max */ List.of(Pair.create(WORK_TYPE_BG, 6)),
+ /* min */ List.of(Pair.create(WORK_TYPE_BG, .25f)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, .75f)),
/* run */ List.of(Pair.create(WORK_TYPE_TOP, 2), Pair.create(WORK_TYPE_BG, 4)),
/* pen */ List.of(Pair.create(WORK_TYPE_BG, 49)),
/* resRun */ List.of(Pair.create(WORK_TYPE_TOP, 2), Pair.create(WORK_TYPE_BG, 6)),
/* resPen */ List.of(Pair.create(WORK_TYPE_BG, 47)));
checkSimple(8,
- /* min */ List.of(Pair.create(WORK_TYPE_BG, 2)),
- /* max */ List.of(Pair.create(WORK_TYPE_BG, 6)),
+ /* min */ List.of(Pair.create(WORK_TYPE_BG, .25f)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, .75f)),
/* run */ List.of(Pair.create(WORK_TYPE_TOP, 2), Pair.create(WORK_TYPE_BG, 4)),
/* pen */ List.of(Pair.create(WORK_TYPE_TOP, 49), Pair.create(WORK_TYPE_BG, 49)),
/* resRun */ List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_BG, 4)),
@@ -686,48 +712,52 @@
checkSimple(8,
- /* min */ List.of(Pair.create(WORK_TYPE_BG, 2)),
- /* max */ List.of(Pair.create(WORK_TYPE_TOP, 6), Pair.create(WORK_TYPE_BG, 6)),
+ /* min */ List.of(Pair.create(WORK_TYPE_BG, .25f)),
+ /* max */
+ List.of(Pair.create(WORK_TYPE_TOP, .75f), Pair.create(WORK_TYPE_BG, .75f)),
/* run */ List.of(Pair.create(WORK_TYPE_TOP, 2), Pair.create(WORK_TYPE_BG, 4)),
/* pen */ List.of(Pair.create(WORK_TYPE_TOP, 10), Pair.create(WORK_TYPE_BG, 49)),
/* resRun */ List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_BG, 4)),
/* resPen */ List.of(Pair.create(WORK_TYPE_TOP, 8), Pair.create(WORK_TYPE_BG, 49)));
checkSimple(8,
- /* min */ List.of(Pair.create(WORK_TYPE_BG, 2)),
- /* max */ List.of(Pair.create(WORK_TYPE_TOP, 6), Pair.create(WORK_TYPE_BG, 6)),
+ /* min */ List.of(Pair.create(WORK_TYPE_BG, .25f)),
+ /* max */ List.of(
+ Pair.create(WORK_TYPE_TOP, .75f), Pair.create(WORK_TYPE_BG, .75f)),
/* run */ List.of(Pair.create(WORK_TYPE_TOP, 2), Pair.create(WORK_TYPE_BG, 1)),
/* pen */ List.of(Pair.create(WORK_TYPE_TOP, 10), Pair.create(WORK_TYPE_BG, 49)),
/* resRun */ List.of(Pair.create(WORK_TYPE_TOP, 6), Pair.create(WORK_TYPE_BG, 2)),
/* resPen */ List.of(Pair.create(WORK_TYPE_TOP, 6), Pair.create(WORK_TYPE_BG, 48)));
checkSimple(8,
- /* min */ List.of(Pair.create(WORK_TYPE_BG, 1)),
- /* max */ List.of(Pair.create(WORK_TYPE_TOP, 6), Pair.create(WORK_TYPE_BG, 2)),
+ /* min */ List.of(Pair.create(WORK_TYPE_BG, 1.0f / 8)),
+ /* max */ List.of(
+ Pair.create(WORK_TYPE_TOP, .75f), Pair.create(WORK_TYPE_BG, .25f)),
/* run */ List.of(Pair.create(WORK_TYPE_BG, 6)),
/* pen */ List.of(Pair.create(WORK_TYPE_TOP, 10), Pair.create(WORK_TYPE_BG, 49)),
/* resRun */ List.of(Pair.create(WORK_TYPE_TOP, 2), Pair.create(WORK_TYPE_BG, 6)),
/* resPen */ List.of(Pair.create(WORK_TYPE_TOP, 8), Pair.create(WORK_TYPE_BG, 49)));
checkSimple(8,
- /* min */ List.of(Pair.create(WORK_TYPE_BG, 1)),
- /* max */ List.of(Pair.create(WORK_TYPE_TOP, 6), Pair.create(WORK_TYPE_BG, 2)),
+ /* min */ List.of(Pair.create(WORK_TYPE_BG, 1.0f / 8)),
+ /* max */
+ List.of(Pair.create(WORK_TYPE_TOP, .75f), Pair.create(WORK_TYPE_BG, .25f)),
/* run */ List.of(Pair.create(WORK_TYPE_BG, 6)),
/* pen */ List.of(Pair.create(WORK_TYPE_TOP, 10), Pair.create(WORK_TYPE_BG, 49)),
/* resRun */ List.of(Pair.create(WORK_TYPE_TOP, 2), Pair.create(WORK_TYPE_BG, 6)),
/* resPen */ List.of(Pair.create(WORK_TYPE_TOP, 8), Pair.create(WORK_TYPE_BG, 49)));
checkSimple(6,
- /* min */ List.of(Pair.create(WORK_TYPE_BG, 2)),
- /* max */ List.of(Pair.create(WORK_TYPE_BG, 4)),
+ /* min */ List.of(Pair.create(WORK_TYPE_BG, 1.0f / 3)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3)),
/* run */ List.of(Pair.create(WORK_TYPE_TOP, 6)),
/* pen */ List.of(Pair.create(WORK_TYPE_TOP, 10), Pair.create(WORK_TYPE_BG, 3)),
/* resRun */ List.of(Pair.create(WORK_TYPE_TOP, 6)),
/* resPen */ List.of(Pair.create(WORK_TYPE_TOP, 10), Pair.create(WORK_TYPE_BG, 3)));
checkSimple(8,
- /* min */ List.of(Pair.create(WORK_TYPE_EJ, 2), Pair.create(WORK_TYPE_BG, 2)),
- /* max */ List.of(Pair.create(WORK_TYPE_BG, 4)),
+ /* min */ List.of(Pair.create(WORK_TYPE_EJ, .25f), Pair.create(WORK_TYPE_BG, .25f)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, .75f)),
/* run */ List.of(Pair.create(WORK_TYPE_TOP, 6)),
/* pen */ List.of(Pair.create(WORK_TYPE_TOP, 10), Pair.create(WORK_TYPE_EJ, 5),
Pair.create(WORK_TYPE_BG, 3)),
@@ -740,15 +770,16 @@
// shouldn't start new ones.
checkSimple(5,
/* min */ List.of(),
- /* max */ List.of(Pair.create(WORK_TYPE_BG, 1)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, .2f)),
/* run */ List.of(Pair.create(WORK_TYPE_BG, 6)),
/* pen */ List.of(Pair.create(WORK_TYPE_TOP, 10), Pair.create(WORK_TYPE_BG, 3)),
/* resRun */ List.of(Pair.create(WORK_TYPE_BG, 6)),
/* resPen */ List.of(Pair.create(WORK_TYPE_TOP, 10), Pair.create(WORK_TYPE_BG, 3)));
checkSimple(6,
- /* min */ List.of(Pair.create(WORK_TYPE_BG, 2)),
- /* max */ List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 2)),
+ /* min */ List.of(Pair.create(WORK_TYPE_BG, 1.0f / 3)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3),
+ Pair.create(WORK_TYPE_BGUSER, 1.0f / 3)),
/* run */ List.of(Pair.create(WORK_TYPE_BG, 2)),
/* pen */ List.of(Pair.create(WORK_TYPE_TOP, 10),
Pair.create(WORK_TYPE_BG, 3),
@@ -759,8 +790,9 @@
Pair.create(WORK_TYPE_BGUSER, 3)));
checkSimple(6,
- /* min */ List.of(Pair.create(WORK_TYPE_BG, 2)),
- /* max */ List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 3)),
+ /* min */ List.of(Pair.create(WORK_TYPE_BG, 1.0f / 3)),
+ /* max */ List.of(
+ Pair.create(WORK_TYPE_BG, 2.0f / 3), Pair.create(WORK_TYPE_BGUSER, .5f)),
/* run */ List.of(Pair.create(WORK_TYPE_BG, 2)),
/* pen */ List.of(Pair.create(WORK_TYPE_BG, 3), Pair.create(WORK_TYPE_BGUSER, 3)),
/* resRun */ List.of(
@@ -769,8 +801,9 @@
Pair.create(WORK_TYPE_BG, 1), Pair.create(WORK_TYPE_BGUSER, 1)));
checkSimple(6,
- /* min */ List.of(Pair.create(WORK_TYPE_BG, 2)),
- /* max */ List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 1)),
+ /* min */ List.of(Pair.create(WORK_TYPE_BG, 1.0f / 3)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3),
+ Pair.create(WORK_TYPE_BGUSER, 1.0f / 6)),
/* run */ List.of(Pair.create(WORK_TYPE_BG, 2)),
/* pen */ List.of(Pair.create(WORK_TYPE_BG, 3), Pair.create(WORK_TYPE_BGUSER, 3)),
/* resRun */ List.of(
@@ -778,12 +811,13 @@
/* resPen */ List.of(
Pair.create(WORK_TYPE_BG, 1), Pair.create(WORK_TYPE_BGUSER, 2)));
- Log.d(TAG, "START***#*#*#*#*#*#**#*");
// Test multi-types
checkSimple(6,
- /* min */ List.of(Pair.create(WORK_TYPE_EJ, 2), Pair.create(WORK_TYPE_BG, 2)),
+ /* min */
+ List.of(Pair.create(WORK_TYPE_EJ, 1.0f / 3), Pair.create(WORK_TYPE_BG, 1.0f / 3)),
/* max */ List.of(
- Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 1)),
+ Pair.create(WORK_TYPE_BG, 2.0f / 3),
+ Pair.create(WORK_TYPE_BGUSER, 1.0f / 6)),
/* run */ List.of(),
/* pen */ List.of(
// 2 of these as TOP, 1 as EJ
@@ -809,10 +843,12 @@
jobs.addPending(WORK_TYPE_BG, 10);
final int totalMax = 6;
- final List<Pair<Integer, Integer>> minLimits = List.of(Pair.create(WORK_TYPE_BG, 1));
- final List<Pair<Integer, Integer>> maxLimits = List.of(Pair.create(WORK_TYPE_BG, 5));
+ final List<Pair<Integer, Float>> minLimitRatios =
+ List.of(Pair.create(WORK_TYPE_BG, 1.0f / totalMax));
+ final List<Pair<Integer, Float>> maxLimitRatios =
+ List.of(Pair.create(WORK_TYPE_BG, 5.0f / totalMax));
- recount(jobs, totalMax, minLimits, maxLimits);
+ recount(jobs, totalMax, minLimitRatios, maxLimitRatios);
startPendingJobs(jobs);
@@ -887,11 +923,12 @@
jobs.addPending(WORK_TYPE_BG, 10); // c
final int totalMax = 8;
- final List<Pair<Integer, Integer>> minLimits =
- List.of(Pair.create(WORK_TYPE_EJ, 1), Pair.create(WORK_TYPE_BG, 1));
- final List<Pair<Integer, Integer>> maxLimits = List.of(Pair.create(WORK_TYPE_BG, 5));
+ final List<Pair<Integer, Float>> minLimitRatios =
+ List.of(Pair.create(WORK_TYPE_EJ, 1.0f / 8), Pair.create(WORK_TYPE_BG, 1.0f / 8));
+ final List<Pair<Integer, Float>> maxLimitRatios =
+ List.of(Pair.create(WORK_TYPE_BG, 5.0f / 8));
- recount(jobs, totalMax, minLimits, maxLimits);
+ recount(jobs, totalMax, minLimitRatios, maxLimitRatios);
assertThat(jobs.pending.get(WORK_TYPE_TOP)).isEqualTo(11);
assertThat(jobs.pending.get(WORK_TYPE_EJ)).isEqualTo(5);
@@ -966,11 +1003,12 @@
}
final int totalMax = 8;
- final List<Pair<Integer, Integer>> minLimits =
- List.of(Pair.create(WORK_TYPE_EJ, 1), Pair.create(WORK_TYPE_BG, 1));
- final List<Pair<Integer, Integer>> maxLimits = List.of(Pair.create(WORK_TYPE_BG, 5));
+ final List<Pair<Integer, Float>> minLimitRatios =
+ List.of(Pair.create(WORK_TYPE_EJ, 1.0f / 8), Pair.create(WORK_TYPE_BG, 1.0f / 8));
+ final List<Pair<Integer, Float>> maxLimitRatios =
+ List.of(Pair.create(WORK_TYPE_BG, 5.0f / 8));
- recount(jobs, totalMax, minLimits, maxLimits);
+ recount(jobs, totalMax, minLimitRatios, maxLimitRatios);
assertThat(jobs.pending.get(WORK_TYPE_TOP)).isEqualTo(11);
assertThat(jobs.pending.get(WORK_TYPE_EJ)).isEqualTo(10);
diff --git a/services/tests/servicestests/src/com/android/server/job/WorkTypeConfigTest.java b/services/tests/servicestests/src/com/android/server/job/WorkTypeConfigTest.java
index 21d2784..bd5a063 100644
--- a/services/tests/servicestests/src/com/android/server/job/WorkTypeConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/WorkTypeConfigTest.java
@@ -45,23 +45,26 @@
@SmallTest
public class WorkTypeConfigTest {
private static final String KEY_MAX_TOTAL = "concurrency_max_total_test";
- private static final String KEY_MAX_TOP = "concurrency_max_top_test";
- private static final String KEY_MAX_FGS = "concurrency_max_fgs_test";
- private static final String KEY_MAX_EJ = "concurrency_max_ej_test";
- private static final String KEY_MAX_BG = "concurrency_max_bg_test";
- private static final String KEY_MAX_BGUSER_IMPORTANT = "concurrency_max_bguser_important_test";
- private static final String KEY_MAX_BGUSER = "concurrency_max_bguser_test";
- private static final String KEY_MIN_TOP = "concurrency_min_top_test";
- private static final String KEY_MIN_FGS = "concurrency_min_fgs_test";
- private static final String KEY_MIN_EJ = "concurrency_min_ej_test";
- private static final String KEY_MIN_BG = "concurrency_min_bg_test";
- private static final String KEY_MIN_BGUSER_IMPORTANT = "concurrency_min_bguser_important_test";
- private static final String KEY_MIN_BGUSER = "concurrency_min_bguser_test";
+ private static final String KEY_MAX_RATIO_TOP = "concurrency_max_ratio_top_test";
+ private static final String KEY_MAX_RATIO_FGS = "concurrency_max_ratio_fgs_test";
+ private static final String KEY_MAX_RATIO_EJ = "concurrency_max_ratio_ej_test";
+ private static final String KEY_MAX_RATIO_BG = "concurrency_max_ratio_bg_test";
+ private static final String KEY_MAX_RATIO_BGUSER_IMPORTANT =
+ "concurrency_max_ratio_bguser_important_test";
+ private static final String KEY_MAX_RATIO_BGUSER = "concurrency_max_ratio_bguser_test";
+ private static final String KEY_MIN_RATIO_TOP = "concurrency_min_ratio_top_test";
+ private static final String KEY_MIN_RATIO_FGS = "concurrency_min_ratio_fgs_test";
+ private static final String KEY_MIN_RATIO_EJ = "concurrency_min_ratio_ej_test";
+ private static final String KEY_MIN_RATIO_BG = "concurrency_min_ratio_bg_test";
+ private static final String KEY_MIN_RATIO_BGUSER_IMPORTANT =
+ "concurrency_min_ratio_bguser_important_test";
+ private static final String KEY_MIN_RATIO_BGUSER = "concurrency_min_ratio_bguser_test";
private void check(@Nullable DeviceConfig.Properties config,
+ int defaultLimit,
int defaultTotal,
- @NonNull List<Pair<Integer, Integer>> defaultMin,
- @NonNull List<Pair<Integer, Integer>> defaultMax,
+ @NonNull List<Pair<Integer, Float>> defaultMinRatios,
+ @NonNull List<Pair<Integer, Float>> defaultMaxRatios,
boolean expectedValid, int expectedTotal,
@NonNull List<Pair<Integer, Integer>> expectedMinLimits,
@NonNull List<Pair<Integer, Integer>> expectedMaxLimits) throws Exception {
@@ -69,7 +72,7 @@
final WorkTypeConfig counts;
try {
counts = new WorkTypeConfig("test",
- defaultTotal, defaultMin, defaultMax);
+ defaultLimit, defaultTotal, defaultMinRatios, defaultMaxRatios);
if (!expectedValid) {
fail("Invalid config successfully created");
return;
@@ -84,7 +87,7 @@
}
if (config != null) {
- counts.update(config);
+ counts.update(config, defaultLimit);
}
assertEquals(expectedTotal, counts.getMaxTotal());
@@ -101,7 +104,7 @@
@Test
public void test() throws Exception {
// Tests with various combinations.
- check(null, /*default*/ 13,
+ check(null, /* limit */ 16, /*default*/ 13,
/* min */ List.of(),
/* max */ List.of(),
/*expected*/ true, 13,
@@ -109,111 +112,141 @@
Pair.create(WORK_TYPE_BG, 0), Pair.create(WORK_TYPE_BGUSER, 0)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 13), Pair.create(WORK_TYPE_EJ, 13),
Pair.create(WORK_TYPE_BG, 13), Pair.create(WORK_TYPE_BGUSER, 13)));
- check(null, /*default*/ 5,
- /* min */ List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_BG, 0)),
- /* max */ List.of(Pair.create(WORK_TYPE_BG, 1)),
+ check(null, /* limit */ 16, /*default*/ 5,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, .8f), Pair.create(WORK_TYPE_BG, 0f)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, .2f)),
/*expected*/ true, 5,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_BG, 0)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 5), Pair.create(WORK_TYPE_BG, 1)));
- check(null, /*default*/ 5,
- /* min */ List.of(Pair.create(WORK_TYPE_TOP, 5),
- Pair.create(WORK_TYPE_BG, 0), Pair.create(WORK_TYPE_BGUSER, 0)),
+ check(null, /* limit */ 16, /*default*/ 5,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, 1f),
+ Pair.create(WORK_TYPE_BG, 0f), Pair.create(WORK_TYPE_BGUSER, 0f)),
/* max */ List.of(
- Pair.create(WORK_TYPE_BG, 0), Pair.create(WORK_TYPE_BGUSER, 1)),
- /*expected*/ true, 5,
+ Pair.create(WORK_TYPE_BG, 0f), Pair.create(WORK_TYPE_BGUSER, .2f)),
+ /*expected*/ false, 5,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 5),
Pair.create(WORK_TYPE_BG, 0), Pair.create(WORK_TYPE_BGUSER, 0)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 5),
Pair.create(WORK_TYPE_BG, 1), Pair.create(WORK_TYPE_BGUSER, 1)));
- check(null, /*default*/ 0,
- /* min */ List.of(Pair.create(WORK_TYPE_TOP, 5), Pair.create(WORK_TYPE_BG, 0)),
- /* max */ List.of(Pair.create(WORK_TYPE_BG, 0)),
- /*expected*/ false, 1,
- /* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 0)),
- /* max */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 1)));
- check(null, /*default*/ -1,
- /* min */ List.of(Pair.create(WORK_TYPE_BG, -1)),
- /* max */ List.of(Pair.create(WORK_TYPE_BG, -1)),
- /*expected*/ false, 1,
- /* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 0)),
- /* max */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 1)));
- check(null, /*default*/ 5,
- /* min */ List.of(
- Pair.create(WORK_TYPE_BG, 5), Pair.create(WORK_TYPE_BGUSER, 0)),
+ check(null, /* limit */ 16, /*default*/ 5,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, .99f),
+ Pair.create(WORK_TYPE_BG, 0f), Pair.create(WORK_TYPE_BGUSER, 0f)),
/* max */ List.of(
- Pair.create(WORK_TYPE_BG, 5), Pair.create(WORK_TYPE_BGUSER, 5)),
+ Pair.create(WORK_TYPE_BG, .01f), Pair.create(WORK_TYPE_BGUSER, .2f)),
+ /*expected*/ true, 5,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, 4),
+ Pair.create(WORK_TYPE_BG, 0), Pair.create(WORK_TYPE_BGUSER, 0)),
+ /* max */ List.of(Pair.create(WORK_TYPE_TOP, 5),
+ Pair.create(WORK_TYPE_BG, 1), Pair.create(WORK_TYPE_BGUSER, 1)));
+ check(null, /* limit */ 16, /*default*/ 0,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, 1f), Pair.create(WORK_TYPE_BG, 0f)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, 0f)),
+ /*expected*/ false, 1,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 0)),
+ /* max */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 1)));
+ check(null, /* limit */ 16, /*default*/ -1,
+ /* min */ List.of(Pair.create(WORK_TYPE_BG, -1f)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, -1f)),
+ /*expected*/ false, 1,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 0)),
+ /* max */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 1)));
+ check(null, /* limit */ 16, /*default*/ 5,
+ /* min */ List.of(
+ Pair.create(WORK_TYPE_BG, 1f), Pair.create(WORK_TYPE_BGUSER, 0f)),
+ /* max */ List.of(
+ Pair.create(WORK_TYPE_BG, 1f), Pair.create(WORK_TYPE_BGUSER, 1f)),
+ /*expected*/ false, 5,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, 1),
+ Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 0)),
+ /* max */ List.of(Pair.create(WORK_TYPE_TOP, 5),
+ Pair.create(WORK_TYPE_BG, 5), Pair.create(WORK_TYPE_BGUSER, 5)));
+ check(null, /* limit */ 16, /*default*/ 5,
+ /* min */ List.of(
+ Pair.create(WORK_TYPE_BG, .99f), Pair.create(WORK_TYPE_BGUSER, 0f)),
+ /* max */ List.of(
+ Pair.create(WORK_TYPE_BG, 1f), Pair.create(WORK_TYPE_BGUSER, 1f)),
/*expected*/ true, 5,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1),
Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 0)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 5),
Pair.create(WORK_TYPE_BG, 5), Pair.create(WORK_TYPE_BGUSER, 5)));
- check(null, /*default*/ 6,
- /* min */ List.of(Pair.create(WORK_TYPE_TOP, 1),
- Pair.create(WORK_TYPE_BG, 6), Pair.create(WORK_TYPE_BGUSER, 2)),
+ check(null, /* limit */ 16, /*default*/ 6,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, 1.0f / 6),
+ Pair.create(WORK_TYPE_BG, 1f), Pair.create(WORK_TYPE_BGUSER, 1.0f / 3)),
/* max */ List.of(
- Pair.create(WORK_TYPE_BG, 5), Pair.create(WORK_TYPE_BGUSER, 1)),
+ Pair.create(WORK_TYPE_BG, 1f), Pair.create(WORK_TYPE_BGUSER, 1.0f / 6)),
/*expected*/ false, 6,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1),
Pair.create(WORK_TYPE_BG, 5), Pair.create(WORK_TYPE_BGUSER, 0)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 6),
Pair.create(WORK_TYPE_BG, 5), Pair.create(WORK_TYPE_BGUSER, 1)));
- check(null, /*default*/ 4,
+ check(null, /* limit */ 16, /*default*/ 4,
/* min */ List.of(
- Pair.create(WORK_TYPE_BG, 6), Pair.create(WORK_TYPE_BGUSER, 6)),
+ Pair.create(WORK_TYPE_BG, 1.5f), Pair.create(WORK_TYPE_BGUSER, 1.5f)),
/* max */ List.of(
- Pair.create(WORK_TYPE_BG, 5), Pair.create(WORK_TYPE_BGUSER, 5)),
+ Pair.create(WORK_TYPE_BG, 1.25f), Pair.create(WORK_TYPE_BGUSER, 1.25f)),
/*expected*/ false, 4,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1),
Pair.create(WORK_TYPE_BG, 3), Pair.create(WORK_TYPE_BGUSER, 0)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 4),
Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 4)));
- check(null, /*default*/ 5,
- /* min */ List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_BG, 1)),
- /* max */ List.of(Pair.create(WORK_TYPE_BG, 1)),
+ check(null, /* limit */ 16, /*default*/ 5,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, .8f), Pair.create(WORK_TYPE_BG, .2f)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, .2f)),
/*expected*/ true, 5,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_BG, 1)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 5), Pair.create(WORK_TYPE_BG, 1)));
- check(null, /*default*/ 10,
- /* min */ List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_EJ, 3),
- Pair.create(WORK_TYPE_BG, 1)),
- /* max */ List.of(Pair.create(WORK_TYPE_BG, 1)),
+ check(null, /* limit */ 16, /*default*/ 10,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, .4f), Pair.create(WORK_TYPE_EJ, .3f),
+ Pair.create(WORK_TYPE_BG, .1f)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, .1f)),
/*expected*/ true, 10,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_EJ, 3),
Pair.create(WORK_TYPE_BG, 1)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 10), Pair.create(WORK_TYPE_BG, 1)));
- check(null, /*default*/ 10,
- /* min */ List.of(Pair.create(WORK_TYPE_TOP, 3), Pair.create(WORK_TYPE_FGS, 2),
- Pair.create(WORK_TYPE_EJ, 1), Pair.create(WORK_TYPE_BG, 1)),
- /* max */ List.of(Pair.create(WORK_TYPE_FGS, 3)),
+ check(null, /* limit */ 16, /*default*/ 10,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, .3f), Pair.create(WORK_TYPE_FGS, .2f),
+ Pair.create(WORK_TYPE_EJ, .1f), Pair.create(WORK_TYPE_BG, .1f)),
+ /* max */ List.of(Pair.create(WORK_TYPE_FGS, .3f)),
/*expected*/ true, 10,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 3), Pair.create(WORK_TYPE_FGS, 2),
Pair.create(WORK_TYPE_EJ, 1), Pair.create(WORK_TYPE_BG, 1)),
/* max */ List.of(Pair.create(WORK_TYPE_FGS, 3)));
- check(null, /*default*/ 15,
- /* min */ List.of(Pair.create(WORK_TYPE_BG, 15)),
- /* max */ List.of(Pair.create(WORK_TYPE_BG, 15)),
+ check(null, /* limit */ 16, /*default*/ 15,
+ /* min */ List.of(Pair.create(WORK_TYPE_BG, .95f)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, 1f)),
/*expected*/ true, 15,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 14)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 15), Pair.create(WORK_TYPE_BG, 15)));
- check(null, /*default*/ 16,
- /* min */ List.of(Pair.create(WORK_TYPE_BG, 16)),
- /* max */ List.of(Pair.create(WORK_TYPE_BG, 16)),
+ check(null, /* limit */ 16, /*default*/ 16,
+ /* min */ List.of(Pair.create(WORK_TYPE_BG, .99f)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, 1f)),
/*expected*/ true, 16,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 15)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 16), Pair.create(WORK_TYPE_BG, 16)));
- check(null, /*default*/ 20,
+ check(null, /* limit */ 16, /*default*/ 20,
/* min */ List.of(
- Pair.create(WORK_TYPE_BG, 20), Pair.create(WORK_TYPE_BGUSER, 10)),
+ Pair.create(WORK_TYPE_BG, .99f), Pair.create(WORK_TYPE_BGUSER, .5f)),
/* max */ List.of(
- Pair.create(WORK_TYPE_BG, 20), Pair.create(WORK_TYPE_BGUSER, 20)),
+ Pair.create(WORK_TYPE_BG, 1f), Pair.create(WORK_TYPE_BGUSER, 1f)),
/*expected*/ false, 16,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1),
Pair.create(WORK_TYPE_BG, 15), Pair.create(WORK_TYPE_BGUSER, 0)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 16),
Pair.create(WORK_TYPE_BG, 16), Pair.create(WORK_TYPE_BGUSER, 16)));
- check(null, /*default*/ 20,
- /* min */ List.of(Pair.create(WORK_TYPE_BG, 16)),
- /* max */ List.of(Pair.create(WORK_TYPE_BG, 16)),
+ check(null, /* limit */ 76, /*default*/ 80,
+ /* min */ List.of(
+ Pair.create(WORK_TYPE_BG, .98f), Pair.create(WORK_TYPE_BGUSER, .9f)),
+ /* max */ List.of(
+ Pair.create(WORK_TYPE_BG, 1f), Pair.create(WORK_TYPE_BGUSER, 1f)),
+ /*expected*/ false, 64,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, 1),
+ Pair.create(WORK_TYPE_BG, 63), Pair.create(WORK_TYPE_BGUSER, 0)),
+ /* max */ List.of(Pair.create(WORK_TYPE_TOP, 64),
+ Pair.create(WORK_TYPE_BG, 64), Pair.create(WORK_TYPE_BGUSER, 64)));
+ check(null, /* limit */ 16, /*default*/ 20,
+ /* min */ List.of(Pair.create(WORK_TYPE_BG, .99f)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, 1f)),
/*expected*/ true, 16,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 15)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 16), Pair.create(WORK_TYPE_BG, 16)));
@@ -221,94 +254,101 @@
// Test for overriding with a setting string.
check(new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER)
.setInt(KEY_MAX_TOTAL, 5)
- .setInt(KEY_MAX_BG, 4)
- .setInt(KEY_MIN_BG, 3)
+ .setFloat(KEY_MAX_RATIO_BG, .8f)
+ .setFloat(KEY_MIN_RATIO_BG, .6f)
.build(),
+ /* limit */ 16,
/*default*/ 9,
- /* min */ List.of(Pair.create(WORK_TYPE_BG, 9)),
+ /* min */ List.of(Pair.create(WORK_TYPE_BG, .99f)),
/* max */ List.of(
- Pair.create(WORK_TYPE_BG, 9), Pair.create(WORK_TYPE_BGUSER, 2)),
+ Pair.create(WORK_TYPE_BG, 1f), Pair.create(WORK_TYPE_BGUSER, .4f)),
/*expected*/ true, 5,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 3)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 5),
Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 2)));
check(new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER)
.setInt(KEY_MAX_TOTAL, 5).build(),
+ /* limit */ 16,
/*default*/ 9,
- /* min */ List.of(Pair.create(WORK_TYPE_BG, 9)),
- /* max */ List.of(Pair.create(WORK_TYPE_BG, 9)),
+ /* min */ List.of(Pair.create(WORK_TYPE_BG, .99f)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, 1f)),
/*expected*/ true, 5,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 4)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 5), Pair.create(WORK_TYPE_BG, 5)));
check(new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER)
- .setInt(KEY_MAX_BG, 4).build(),
+ .setFloat(KEY_MAX_RATIO_BG, 4.0f / 9).build(),
+ /* limit */ 16,
/*default*/ 9,
- /* min */ List.of(Pair.create(WORK_TYPE_BG, 9)),
- /* max */ List.of(Pair.create(WORK_TYPE_BG, 9)),
+ /* min */ List.of(Pair.create(WORK_TYPE_BG, .99f)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, 1f)),
/*expected*/ true, 9,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 4)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 9), Pair.create(WORK_TYPE_BG, 4)));
check(new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER)
- .setInt(KEY_MIN_BG, 3).build(),
+ .setFloat(KEY_MIN_RATIO_BG, 1.0f / 3).build(),
+ /* limit */ 16,
/*default*/ 9,
- /* min */ List.of(Pair.create(WORK_TYPE_BG, 9)),
- /* max */ List.of(Pair.create(WORK_TYPE_BG, 9)),
+ /* min */ List.of(Pair.create(WORK_TYPE_BG, .99f)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, 1f)),
/*expected*/ true, 9,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 3)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 9), Pair.create(WORK_TYPE_BG, 9)));
check(new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER)
.setInt(KEY_MAX_TOTAL, 20)
- .setInt(KEY_MAX_EJ, 5)
- .setInt(KEY_MIN_EJ, 2)
- .setInt(KEY_MAX_BG, 16)
- .setInt(KEY_MIN_BG, 8)
+ .setFloat(KEY_MAX_RATIO_EJ, .25f)
+ .setFloat(KEY_MIN_RATIO_EJ, .1f)
+ .setFloat(KEY_MAX_RATIO_BG, .8f)
+ .setFloat(KEY_MIN_RATIO_BG, .4f)
.build(),
+ /* limit */ 16,
/*default*/ 9,
- /* min */ List.of(Pair.create(WORK_TYPE_BG, 9)),
- /* max */ List.of(Pair.create(WORK_TYPE_BG, 9)),
+ /* min */ List.of(Pair.create(WORK_TYPE_BG, .99f)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, 1f)),
/*expected*/ true, 16,
- /* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_EJ, 2),
- Pair.create(WORK_TYPE_BG, 8)),
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_EJ, 1),
+ Pair.create(WORK_TYPE_BG, 6)),
/* max */
- List.of(Pair.create(WORK_TYPE_TOP, 16), Pair.create(WORK_TYPE_EJ, 5),
- Pair.create(WORK_TYPE_BG, 16)));
+ List.of(Pair.create(WORK_TYPE_TOP, 16), Pair.create(WORK_TYPE_EJ, 4),
+ Pair.create(WORK_TYPE_BG, 12)));
check(new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER)
.setInt(KEY_MAX_TOTAL, 20)
- .setInt(KEY_MAX_BG, 20)
- .setInt(KEY_MIN_BG, 8)
+ .setFloat(KEY_MAX_RATIO_BG, 1f)
+ .setFloat(KEY_MIN_RATIO_BG, .4f)
.build(),
+ /* limit */ 16,
/*default*/ 9,
- /* min */ List.of(Pair.create(WORK_TYPE_BG, 9)),
- /* max */ List.of(Pair.create(WORK_TYPE_BG, 9)),
+ /* min */ List.of(Pair.create(WORK_TYPE_BG, .99f)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, 1f)),
/*expected*/ true, 16,
- /* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 8)),
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 6)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 16), Pair.create(WORK_TYPE_BG, 16)));
check(new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER)
.setInt(KEY_MAX_TOTAL, 16)
- .setInt(KEY_MAX_TOP, 16)
- .setInt(KEY_MIN_TOP, 1)
- .setInt(KEY_MAX_FGS, 15)
- .setInt(KEY_MIN_FGS, 2)
- .setInt(KEY_MAX_EJ, 14)
- .setInt(KEY_MIN_EJ, 3)
- .setInt(KEY_MAX_BG, 13)
- .setInt(KEY_MIN_BG, 4)
- .setInt(KEY_MAX_BGUSER_IMPORTANT, 12)
- .setInt(KEY_MIN_BGUSER_IMPORTANT, 5)
- .setInt(KEY_MAX_BGUSER, 11)
- .setInt(KEY_MIN_BGUSER, 6)
+ .setFloat(KEY_MAX_RATIO_TOP, 1f)
+ .setFloat(KEY_MIN_RATIO_TOP, 1.0f / 16)
+ .setFloat(KEY_MAX_RATIO_FGS, 15.0f / 16)
+ .setFloat(KEY_MIN_RATIO_FGS, 2.0f / 16)
+ .setFloat(KEY_MAX_RATIO_EJ, 14.0f / 16)
+ .setFloat(KEY_MIN_RATIO_EJ, 3.0f / 16)
+ .setFloat(KEY_MAX_RATIO_BG, 13.0f / 16)
+ .setFloat(KEY_MIN_RATIO_BG, 3.0f / 16)
+ .setFloat(KEY_MAX_RATIO_BGUSER_IMPORTANT, 12.0f / 16)
+ .setFloat(KEY_MIN_RATIO_BGUSER_IMPORTANT, 2.0f / 16)
+ .setFloat(KEY_MAX_RATIO_BGUSER, 11.0f / 16)
+ .setFloat(KEY_MIN_RATIO_BGUSER, 2.0f / 16)
.build(),
+ /* limit */ 16,
/*default*/ 9,
- /* min */ List.of(Pair.create(WORK_TYPE_BG, 9)),
- /* max */ List.of(Pair.create(WORK_TYPE_BG, 9)),
+ /* min */ List.of(Pair.create(WORK_TYPE_BG, .99f)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, 1f)),
/*expected*/ true, 16,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_FGS, 2),
- Pair.create(WORK_TYPE_EJ, 3), Pair.create(WORK_TYPE_BG, 4),
- Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 5),
- Pair.create(WORK_TYPE_BGUSER, 6)),
+ Pair.create(WORK_TYPE_EJ, 3), Pair.create(WORK_TYPE_BG, 3),
+ Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 2),
+ Pair.create(WORK_TYPE_BGUSER, 2)),
/* max */
List.of(Pair.create(WORK_TYPE_TOP, 16), Pair.create(WORK_TYPE_FGS, 15),
Pair.create(WORK_TYPE_EJ, 14), Pair.create(WORK_TYPE_BG, 13),
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java
index 41e3a08..60a033f 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java
@@ -423,6 +423,21 @@
checkPasswordHistoryLength(userId, 3);
}
+ @Test(expected=NullPointerException.class)
+ public void testSetBooleanRejectsNullKey() {
+ mService.setBoolean(null, false, 0);
+ }
+
+ @Test(expected=NullPointerException.class)
+ public void testSetLongRejectsNullKey() {
+ mService.setLong(null, 0, 0);
+ }
+
+ @Test(expected=NullPointerException.class)
+ public void testSetStringRejectsNullKey() {
+ mService.setString(null, "value", 0);
+ }
+
private void checkPasswordHistoryLength(int userId, int expectedLen) {
String history = mService.getString(LockPatternUtils.PASSWORD_HISTORY_KEY, "", userId);
String[] hashes = TextUtils.split(history, LockPatternUtils.PASSWORD_HISTORY_DELIMITER);
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java
index 03d5b17..05208441e 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java
@@ -266,6 +266,20 @@
}
@Test
+ public void testNullKey() {
+ mStorage.setString(null, "value", 0);
+
+ // Verify that this doesn't throw an exception.
+ assertEquals("value", mStorage.readKeyValue(null, null, 0));
+
+ // The read that happens as part of prefetchUser shouldn't throw an exception either.
+ mStorage.clearCache();
+ mStorage.prefetchUser(0);
+
+ assertEquals("value", mStorage.readKeyValue(null, null, 0));
+ }
+
+ @Test
public void testRemoveUser() {
mStorage.writeKeyValue("key", "value", 0);
mStorage.writeKeyValue("key", "value", 1);
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
index 281195d..1b983f0b 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
@@ -1073,7 +1073,9 @@
int uid = Binder.getCallingUid();
PendingIntent intent = PendingIntent.getBroadcast(
InstrumentationRegistry.getTargetContext(), /*requestCode=*/1,
- new Intent(), /*flags=*/ PendingIntent.FLAG_MUTABLE_UNAUDITED);
+ new Intent()
+ .setPackage(InstrumentationRegistry.getTargetContext().getPackageName()),
+ /*flags=*/ PendingIntent.FLAG_MUTABLE);
mRecoverableKeyStoreManager.setSnapshotCreatedPendingIntent(intent);
verify(mMockListenersStorage).setSnapshotListener(eq(uid), any(PendingIntent.class));
}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverySnapshotListenersStorageTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverySnapshotListenersStorageTest.java
index d9ebb4c..418d474 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverySnapshotListenersStorageTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverySnapshotListenersStorageTest.java
@@ -41,7 +41,9 @@
int recoveryAgentUid = 1000;
PendingIntent intent = PendingIntent.getBroadcast(
InstrumentationRegistry.getTargetContext(), /*requestCode=*/ 1,
- new Intent(), /*flags=*/ PendingIntent.FLAG_MUTABLE_UNAUDITED);
+ new Intent()
+ .setPackage(InstrumentationRegistry.getTargetContext().getPackageName()),
+ /*flags=*/ PendingIntent.FLAG_MUTABLE);
mStorage.setSnapshotListener(recoveryAgentUid, intent);
assertTrue(mStorage.hasListener(recoveryAgentUid));
@@ -54,7 +56,9 @@
int recoveryAgentUid = 1000;
mStorage.recoverySnapshotAvailable(recoveryAgentUid);
PendingIntent intent = PendingIntent.getBroadcast(
- context, /*requestCode=*/ 0, new Intent(TEST_INTENT_ACTION), /*flags=*/PendingIntent.FLAG_MUTABLE_UNAUDITED);
+ context, /*requestCode=*/ 0,
+ new Intent(TEST_INTENT_ACTION).setPackage(context.getPackageName()),
+ /*flags=*/PendingIntent.FLAG_MUTABLE);
CountDownLatch latch = new CountDownLatch(1);
context.registerReceiver(new BroadcastReceiver() {
@Override
@@ -75,7 +79,9 @@
int recoveryAgentUid = 1000;
mStorage.recoverySnapshotAvailable(recoveryAgentUid);
PendingIntent intent = PendingIntent.getBroadcast(
- context, /*requestCode=*/ 0, new Intent(TEST_INTENT_ACTION), /*flags=*/PendingIntent.FLAG_MUTABLE_UNAUDITED);
+ context, /*requestCode=*/ 0,
+ new Intent(TEST_INTENT_ACTION).setPackage(context.getPackageName()),
+ /*flags=*/PendingIntent.FLAG_MUTABLE);
CountDownLatch latch = new CountDownLatch(2);
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
diff --git a/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkManagementServiceTest.java
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java
rename to services/tests/servicestests/src/com/android/server/net/NetworkManagementServiceTest.java
index 17a5876..d9cd77d 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkManagementServiceTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server;
+package com.android.server.net;
import static android.net.ConnectivityManager.FIREWALL_CHAIN_DOZABLE;
import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY;
@@ -51,14 +51,13 @@
import android.os.Process;
import android.os.RemoteException;
import android.permission.PermissionCheckerManager;
+import android.platform.test.annotations.Presubmit;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.ArrayMap;
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.app.IBatteryStats;
-import com.android.server.NetworkManagementService.Dependencies;
-import com.android.server.net.BaseNetworkObserver;
import org.junit.After;
import org.junit.Before;
@@ -76,6 +75,7 @@
*/
@RunWith(AndroidJUnit4.class)
@SmallTest
+@Presubmit
public class NetworkManagementServiceTest {
private NetworkManagementService mNMService;
@Mock private Context mContext;
@@ -92,7 +92,7 @@
private final MockDependencies mDeps = new MockDependencies();
private final MockPermissionEnforcer mPermissionEnforcer = new MockPermissionEnforcer();
- private final class MockDependencies extends Dependencies {
+ private final class MockDependencies extends NetworkManagementService.Dependencies {
@Override
public IBinder getService(String name) {
switch (name) {
diff --git a/services/tests/servicestests/src/com/android/server/people/data/ContactsQueryHelperTest.java b/services/tests/servicestests/src/com/android/server/people/data/ContactsQueryHelperTest.java
index 96302b9..299f153 100644
--- a/services/tests/servicestests/src/com/android/server/people/data/ContactsQueryHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/people/data/ContactsQueryHelperTest.java
@@ -25,6 +25,7 @@
import android.database.Cursor;
import android.database.MatrixCursor;
+import android.database.sqlite.SQLiteException;
import android.net.Uri;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
@@ -63,6 +64,7 @@
private MatrixCursor mContactsLookupCursor;
private MatrixCursor mPhoneCursor;
private ContactsQueryHelper mHelper;
+ private ContactsContentProvider contentProvider;
@Before
public void setUp() {
@@ -73,7 +75,7 @@
mPhoneCursor = new MatrixCursor(PHONE_COLUMNS);
MockContentResolver contentResolver = new MockContentResolver();
- ContactsContentProvider contentProvider = new ContactsContentProvider();
+ contentProvider = new ContactsContentProvider();
contentProvider.registerCursor(Contacts.CONTENT_URI, mContactsCursor);
contentProvider.registerCursor(
ContactsContract.PhoneLookup.CONTENT_FILTER_URI, mContactsLookupCursor);
@@ -89,6 +91,14 @@
}
@Test
+ public void testQueryException_returnsFalse() {
+ contentProvider.setThrowException(true);
+
+ Uri contactUri = Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, CONTACT_LOOKUP_KEY);
+ assertFalse(mHelper.query(contactUri.toString()));
+ }
+
+ @Test
public void testQueryWithUri() {
mContactsCursor.addRow(new Object[] {
/* id= */ 11, CONTACT_LOOKUP_KEY, /* starred= */ 1, /* hasPhoneNumber= */ 1,
@@ -168,10 +178,15 @@
private class ContactsContentProvider extends MockContentProvider {
private Map<Uri, Cursor> mUriPrefixToCursorMap = new ArrayMap<>();
+ private boolean throwException = false;
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
+ if (throwException) {
+ throw new SQLiteException();
+ }
+
for (Uri prefixUri : mUriPrefixToCursorMap.keySet()) {
if (uri.isPathPrefixMatch(prefixUri)) {
return mUriPrefixToCursorMap.get(prefixUri);
@@ -180,6 +195,10 @@
return mUriPrefixToCursorMap.get(uri);
}
+ public void setThrowException(boolean throwException) {
+ this.throwException = throwException;
+ }
+
private void registerCursor(Uri uriPrefix, Cursor cursor) {
mUriPrefixToCursorMap.put(uriPrefix, cursor);
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/BackgroundInstallControlServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/BackgroundInstallControlServiceTest.java
index d80aa57..ccf530f 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BackgroundInstallControlServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BackgroundInstallControlServiceTest.java
@@ -539,7 +539,8 @@
NoSuchFieldException, PackageManager.NameNotFoundException {
assertNull(mBackgroundInstallControlService.getBackgroundInstalledPackages());
InstallSourceInfo installSourceInfo = new InstallSourceInfo(
- /* initiatingPackageName = */ null, /* initiatingPackageSigningInfo = */ null,
+ /* initiatingPackageName = */ INSTALLER_NAME_1,
+ /* initiatingPackageSigningInfo = */ null,
/* originatingPackageName = */ null,
/* installingPackageName = */ INSTALLER_NAME_1);
assertEquals(installSourceInfo.getInstallingPackageName(), INSTALLER_NAME_1);
@@ -575,7 +576,8 @@
NoSuchFieldException, PackageManager.NameNotFoundException {
assertNull(mBackgroundInstallControlService.getBackgroundInstalledPackages());
InstallSourceInfo installSourceInfo = new InstallSourceInfo(
- /* initiatingPackageName = */ null, /* initiatingPackageSigningInfo = */ null,
+ /* initiatingPackageName = */ INSTALLER_NAME_1,
+ /* initiatingPackageSigningInfo = */ null,
/* originatingPackageName = */ null,
/* installingPackageName = */ INSTALLER_NAME_1);
assertEquals(installSourceInfo.getInstallingPackageName(), INSTALLER_NAME_1);
@@ -619,7 +621,8 @@
NoSuchFieldException, PackageManager.NameNotFoundException {
assertNull(mBackgroundInstallControlService.getBackgroundInstalledPackages());
InstallSourceInfo installSourceInfo = new InstallSourceInfo(
- /* initiatingPackageName = */ null, /* initiatingPackageSigningInfo = */ null,
+ /* initiatingPackageName = */ INSTALLER_NAME_1,
+ /* initiatingPackageSigningInfo = */ null,
/* originatingPackageName = */ null,
/* installingPackageName = */ INSTALLER_NAME_1);
assertEquals(installSourceInfo.getInstallingPackageName(), INSTALLER_NAME_1);
@@ -667,7 +670,8 @@
NoSuchFieldException, PackageManager.NameNotFoundException {
assertNull(mBackgroundInstallControlService.getBackgroundInstalledPackages());
InstallSourceInfo installSourceInfo = new InstallSourceInfo(
- /* initiatingPackageName = */ null, /* initiatingPackageSigningInfo = */ null,
+ /* initiatingPackageName = */ INSTALLER_NAME_1,
+ /* initiatingPackageSigningInfo = */ null,
/* originatingPackageName = */ null,
/* installingPackageName = */ INSTALLER_NAME_1);
assertEquals(installSourceInfo.getInstallingPackageName(), INSTALLER_NAME_1);
@@ -711,7 +715,52 @@
assertEquals(1, packages.size());
assertTrue(packages.contains(USER_ID_1, PACKAGE_NAME_1));
}
+ @Test
+ public void testHandleUsageEvent_packageAddedThroughAdb() throws
+ NoSuchFieldException, PackageManager.NameNotFoundException {
+ assertNull(mBackgroundInstallControlService.getBackgroundInstalledPackages());
+ InstallSourceInfo installSourceInfo = new InstallSourceInfo(
+ /* initiatingPackageName = */ null, //currently ADB installer sets field to null
+ /* initiatingPackageSigningInfo = */ null,
+ /* originatingPackageName = */ null,
+ /* installingPackageName = */ INSTALLER_NAME_1);
+ // b/265203007
+ when(mPackageManager.getInstallSourceInfo(anyString())).thenReturn(installSourceInfo);
+ ApplicationInfo appInfo = mock(ApplicationInfo.class);
+ when(mPackageManager.getApplicationInfoAsUser(
+ eq(PACKAGE_NAME_1),
+ any(),
+ anyInt())
+ ).thenReturn(appInfo);
+
+ long createTimestamp = PACKAGE_ADD_TIMESTAMP_1
+ - (System.currentTimeMillis() - SystemClock.uptimeMillis());
+ FieldSetter.setField(appInfo,
+ ApplicationInfo.class.getDeclaredField("createTimestamp"),
+ createTimestamp);
+
+ int uid = USER_ID_1 * UserHandle.PER_USER_RANGE;
+ assertEquals(USER_ID_1, UserHandle.getUserId(uid));
+
+ // The following usage events generation is the same as
+ // testHandleUsageEvent_packageAddedOutsideTimeFrame2 test. The only difference is that
+ // for ADB installs the initiatingPackageName is null, despite being detected as a
+ // background install. Since we do not want to treat side-loaded apps as background install
+ // getBackgroundInstalledPackages() is expected to return null
+ doReturn(PackageManager.PERMISSION_GRANTED).when(mPermissionManager).checkPermission(
+ anyString(), anyString(), anyInt());
+ generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED,
+ USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_2);
+ generateUsageEvent(Event.ACTIVITY_STOPPED,
+ USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_3);
+
+ mPackageListObserver.onPackageAdded(PACKAGE_NAME_1, uid);
+ mTestLooper.dispatchAll();
+
+ var packages = mBackgroundInstallControlService.getBackgroundInstalledPackages();
+ assertNull(packages);
+ }
@Test
public void testPackageRemoved() {
assertNull(mBackgroundInstallControlService.getBackgroundInstalledPackages());
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java
index 2293808..a85c722 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java
@@ -327,7 +327,9 @@
}
private IntentSender makeResultIntent() {
- return PendingIntent.getActivity(getTestContext(), 0, new Intent(), PendingIntent.FLAG_MUTABLE_UNAUDITED).getIntentSender();
+ return PendingIntent.getActivity(getTestContext(), 0,
+ new Intent().setPackage(getTestContext().getPackageName()),
+ PendingIntent.FLAG_MUTABLE).getIntentSender();
}
public void testRequestPinShortcut_withCallback() {
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java
index a47a8df..2fca3d0 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java
@@ -150,7 +150,9 @@
public void testRequestPinAppWidget_withCallback() {
final PendingIntent resultIntent =
- PendingIntent.getActivity(getTestContext(), 0, new Intent(), PendingIntent.FLAG_MUTABLE_UNAUDITED);
+ PendingIntent.getActivity(getTestContext(), 0,
+ new Intent().setPackage(getTestContext().getPackageName()),
+ PendingIntent.FLAG_MUTABLE);
checkRequestPinAppWidget(resultIntent);
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserLifecycleStressTest.java b/services/tests/servicestests/src/com/android/server/pm/UserLifecycleStressTest.java
index b00fb92..bbe8907 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserLifecycleStressTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserLifecycleStressTest.java
@@ -29,7 +29,6 @@
import android.os.RemoteException;
import android.os.UserManager;
import android.platform.test.annotations.Postsubmit;
-import android.provider.Settings;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
@@ -38,7 +37,6 @@
import com.android.internal.util.FunctionalUtils;
-import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -64,22 +62,12 @@
private Context mContext;
private UserManager mUserManager;
private ActivityManager mActivityManager;
- private String mRemoveGuestOnExitOriginalValue;
@Before
public void setup() {
mContext = InstrumentationRegistry.getInstrumentation().getContext();
mUserManager = mContext.getSystemService(UserManager.class);
mActivityManager = mContext.getSystemService(ActivityManager.class);
- mRemoveGuestOnExitOriginalValue = Settings.Global.getString(mContext.getContentResolver(),
- Settings.Global.REMOVE_GUEST_ON_EXIT);
-
- }
-
- @After
- public void tearDown() {
- Settings.Global.putString(mContext.getContentResolver(),
- Settings.Global.REMOVE_GUEST_ON_EXIT, mRemoveGuestOnExitOriginalValue);
}
/**
@@ -117,9 +105,6 @@
**/
@Test
public void switchToExistingGuestAndStartOverStressTest() throws Exception {
- Settings.Global.putString(mContext.getContentResolver(),
- Settings.Global.REMOVE_GUEST_ON_EXIT, "0");
-
if (ActivityManager.getCurrentUser() != USER_SYSTEM) {
switchUser(USER_SYSTEM);
}
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryExternalStatsWorkerTest.java b/services/tests/servicestests/src/com/android/server/power/stats/BatteryExternalStatsWorkerTest.java
index 2ebe215..cff4cc7 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryExternalStatsWorkerTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/stats/BatteryExternalStatsWorkerTest.java
@@ -18,6 +18,7 @@
import static com.android.server.power.stats.BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL;
import static com.android.server.power.stats.BatteryStatsImpl.ExternalStatsSync.UPDATE_BT;
+import static com.android.server.power.stats.BatteryStatsImpl.ExternalStatsSync.UPDATE_CAMERA;
import static com.android.server.power.stats.BatteryStatsImpl.ExternalStatsSync.UPDATE_CPU;
import static com.android.server.power.stats.BatteryStatsImpl.ExternalStatsSync.UPDATE_DISPLAY;
import static com.android.server.power.stats.BatteryStatsImpl.ExternalStatsSync.UPDATE_RADIO;
@@ -104,6 +105,11 @@
tempAllIds.add(gnssId);
mPowerStatsInternal.incrementEnergyConsumption(gnssId, 787878);
+ final int cameraId =
+ mPowerStatsInternal.addEnergyConsumer(EnergyConsumerType.CAMERA, 0, "camera");
+ tempAllIds.add(cameraId);
+ mPowerStatsInternal.incrementEnergyConsumption(cameraId, 901234);
+
final int mobileRadioId = mPowerStatsInternal.addEnergyConsumer(
EnergyConsumerType.MOBILE_RADIO, 0, "mobile_radio");
tempAllIds.add(mobileRadioId);
@@ -171,6 +177,12 @@
Arrays.sort(receivedCpuIds);
assertArrayEquals(cpuClusterIds, receivedCpuIds);
+ final EnergyConsumerResult[] cameraResults =
+ mBatteryExternalStatsWorker.getEnergyConsumersLocked(UPDATE_CAMERA).getNow(null);
+ // Results should only have the camera energy consumer
+ assertEquals(1, cameraResults.length);
+ assertEquals(cameraId, cameraResults[0].id);
+
final EnergyConsumerResult[] allResults =
mBatteryExternalStatsWorker.getEnergyConsumersLocked(UPDATE_ALL).getNow(null);
// All energy consumer results should be available
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryUsageStatsRule.java b/services/tests/servicestests/src/com/android/server/power/stats/BatteryUsageStatsRule.java
index bf2faac..3135215 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryUsageStatsRule.java
+++ b/services/tests/servicestests/src/com/android/server/power/stats/BatteryUsageStatsRule.java
@@ -137,6 +137,13 @@
return this;
}
+ public BatteryUsageStatsRule setPerUidModemModel(int perUidModemModel) {
+ synchronized (mBatteryStats) {
+ mBatteryStats.setPerUidModemModel(perUidModemModel);
+ }
+ return this;
+ }
+
/** Call only after setting the power profile information. */
public BatteryUsageStatsRule initMeasuredEnergyStatsLocked() {
return initMeasuredEnergyStatsLocked(new String[0]);
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/CameraPowerCalculatorTest.java b/services/tests/servicestests/src/com/android/server/power/stats/CameraPowerCalculatorTest.java
index e4ab21b..5fce32f0 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/CameraPowerCalculatorTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/stats/CameraPowerCalculatorTest.java
@@ -36,41 +36,113 @@
public class CameraPowerCalculatorTest {
private static final double PRECISION = 0.00001;
- private static final int APP_UID = Process.FIRST_APPLICATION_UID + 42;
+ private static final int APP1_UID = Process.FIRST_APPLICATION_UID + 42;
+ private static final int APP2_UID = Process.FIRST_APPLICATION_UID + 43;
@Rule
public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule()
- .setAveragePower(PowerProfile.POWER_CAMERA, 360.0);
+ .setAveragePower(PowerProfile.POWER_CAMERA, 360.0)
+ .initMeasuredEnergyStatsLocked();
@Test
public void testTimerBasedModel() {
BatteryStatsImpl stats = mStatsRule.getBatteryStats();
- stats.noteCameraOnLocked(APP_UID, 1000, 1000);
- stats.noteCameraOffLocked(APP_UID, 2000, 2000);
+ synchronized (stats) { // To keep the GuardedBy check happy
+ stats.noteCameraOnLocked(APP1_UID, 1000, 1000);
+ stats.noteCameraOffLocked(APP1_UID, 2000, 2000);
+ stats.noteCameraOnLocked(APP2_UID, 3000, 3000);
+ stats.noteCameraOffLocked(APP2_UID, 5000, 5000);
+ }
+
+ CameraPowerCalculator calculator =
+ new CameraPowerCalculator(mStatsRule.getPowerProfile());
+
+ mStatsRule.apply(BatteryUsageStatsRule.POWER_PROFILE_MODEL_ONLY, calculator);
+
+ UidBatteryConsumer app1Consumer = mStatsRule.getUidBatteryConsumer(APP1_UID);
+ assertThat(app1Consumer.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_CAMERA))
+ .isEqualTo(1000);
+ assertThat(app1Consumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_CAMERA))
+ .isWithin(PRECISION).of(0.1);
+ assertThat(app1Consumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_CAMERA))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE);
+
+ UidBatteryConsumer app2Consumer = mStatsRule.getUidBatteryConsumer(APP2_UID);
+ assertThat(app2Consumer.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_CAMERA))
+ .isEqualTo(2000);
+ assertThat(app2Consumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_CAMERA))
+ .isWithin(PRECISION).of(0.2);
+ assertThat(app2Consumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_CAMERA))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE);
+
+ final BatteryConsumer deviceBatteryConsumer = mStatsRule.getDeviceBatteryConsumer();
+ assertThat(deviceBatteryConsumer
+ .getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_CAMERA))
+ .isEqualTo(3000);
+ assertThat(deviceBatteryConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_CAMERA))
+ .isWithin(PRECISION).of(0.3);
+ assertThat(deviceBatteryConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_CAMERA))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE);
+
+ final BatteryConsumer appsBatteryConsumer = mStatsRule.getAppsBatteryConsumer();
+ assertThat(appsBatteryConsumer
+ .getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_CAMERA))
+ .isEqualTo(3000);
+ assertThat(appsBatteryConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_CAMERA))
+ .isWithin(PRECISION).of(0.3);
+ assertThat(appsBatteryConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_CAMERA))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE);
+ }
+
+ @Test
+ public void testEnergyConsumptionBasedModel() {
+ BatteryStatsImpl stats = mStatsRule.getBatteryStats();
+ synchronized (stats) { // To keep the GuardedBy check happy
+ stats.noteCameraOnLocked(APP1_UID, 1000, 1000);
+ stats.noteCameraOffLocked(APP1_UID, 2000, 2000);
+ stats.updateCameraEnergyConsumerStatsLocked(720_000, 2100); // 0.72C == 0.2mAh
+ stats.noteCameraOnLocked(APP2_UID, 3000, 3000);
+ stats.noteCameraOffLocked(APP2_UID, 5000, 5000);
+ stats.updateCameraEnergyConsumerStatsLocked(1_080_000, 5100); // 0.3mAh
+ }
CameraPowerCalculator calculator =
new CameraPowerCalculator(mStatsRule.getPowerProfile());
mStatsRule.apply(calculator);
- UidBatteryConsumer consumer = mStatsRule.getUidBatteryConsumer(APP_UID);
- assertThat(consumer.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_CAMERA))
+ UidBatteryConsumer app1Consumer = mStatsRule.getUidBatteryConsumer(APP1_UID);
+ assertThat(app1Consumer.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_CAMERA))
.isEqualTo(1000);
- assertThat(consumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_CAMERA))
- .isWithin(PRECISION).of(0.1);
+ assertThat(app1Consumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_CAMERA))
+ .isWithin(PRECISION).of(0.2);
+ assertThat(app1Consumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_CAMERA))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION);
+
+ UidBatteryConsumer app2Consumer = mStatsRule.getUidBatteryConsumer(APP2_UID);
+ assertThat(app2Consumer.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_CAMERA))
+ .isEqualTo(2000);
+ assertThat(app2Consumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_CAMERA))
+ .isWithin(PRECISION).of(0.3);
+ assertThat(app2Consumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_CAMERA))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION);
final BatteryConsumer deviceBatteryConsumer = mStatsRule.getDeviceBatteryConsumer();
assertThat(deviceBatteryConsumer
.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_CAMERA))
- .isEqualTo(1000);
+ .isEqualTo(3000);
assertThat(deviceBatteryConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_CAMERA))
- .isWithin(PRECISION).of(0.1);
+ .isWithin(PRECISION).of(0.5);
+ assertThat(deviceBatteryConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_CAMERA))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION);
final BatteryConsumer appsBatteryConsumer = mStatsRule.getAppsBatteryConsumer();
assertThat(appsBatteryConsumer
.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_CAMERA))
- .isEqualTo(1000);
+ .isEqualTo(3000);
assertThat(appsBatteryConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_CAMERA))
- .isWithin(PRECISION).of(0.1);
+ .isWithin(PRECISION).of(0.5);
+ assertThat(appsBatteryConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_CAMERA))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/EnergyConsumerSnapshotTest.java b/services/tests/servicestests/src/com/android/server/power/stats/EnergyConsumerSnapshotTest.java
index 558f396..28f4799 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/EnergyConsumerSnapshotTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/stats/EnergyConsumerSnapshotTest.java
@@ -248,6 +248,32 @@
assertThat(details.toString()).isEqualTo("DISPLAY=2667 HPU=3200000 GPU=0 IPU &_=0");
}
+ @Test
+ public void testUpdateAndGetDelta_updatesCameraCharge() {
+ EnergyConsumer cameraConsumer =
+ createEnergyConsumer(7, 0, EnergyConsumerType.CAMERA, "CAMERA");
+ final EnergyConsumerSnapshot snapshot =
+ new EnergyConsumerSnapshot(createIdToConsumerMap(cameraConsumer));
+
+ // An initial result with only one energy consumer
+ EnergyConsumerResult[] result0 = new EnergyConsumerResult[]{
+ createEnergyConsumerResult(cameraConsumer.id, 60_000, null, null),
+ };
+ snapshot.updateAndGetDelta(result0, VOLTAGE_1);
+
+ // A subsequent result
+ EnergyConsumerResult[] result1 = new EnergyConsumerResult[]{
+ createEnergyConsumerResult(cameraConsumer.id, 90_000, null, null),
+ };
+ EnergyConsumerDeltaData delta = snapshot.updateAndGetDelta(result1, VOLTAGE_1);
+
+ // Verify that the delta between the two results is reported.
+ BatteryStats.EnergyConsumerDetails details = snapshot.getEnergyConsumerDetails(delta);
+ assertThat(details.consumers).hasLength(1);
+ long expectedDeltaUC = calculateChargeConsumedUC(60_000, VOLTAGE_1, 90_000, VOLTAGE_1);
+ assertThat(details.chargeUC[0]).isEqualTo(expectedDeltaUC);
+ }
+
private static EnergyConsumer createEnergyConsumer(int id, int ord, byte type, String name) {
final EnergyConsumer ec = new EnergyConsumer();
ec.id = id;
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/MobileRadioPowerCalculatorTest.java b/services/tests/servicestests/src/com/android/server/power/stats/MobileRadioPowerCalculatorTest.java
index 65e6486..d059472 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/MobileRadioPowerCalculatorTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/stats/MobileRadioPowerCalculatorTest.java
@@ -574,8 +574,10 @@
}
@Test
- public void testMeasuredEnergyBasedModel() {
+ public void testMeasuredEnergyBasedModel_mobileRadioActiveTimeModel() {
mStatsRule.setTestPowerProfile(R.xml.power_profile_test_legacy_modem)
+ .setPerUidModemModel(
+ BatteryStatsImpl.PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME)
.initMeasuredEnergyStatsLocked();
BatteryStatsImpl stats = mStatsRule.getBatteryStats();
@@ -637,6 +639,263 @@
.isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION);
}
+
+
+ @Test
+ public void testMeasuredEnergyBasedModel_modemActivityInfoRxTxModel() {
+ mStatsRule.setTestPowerProfile(R.xml.power_profile_test_modem_calculator_multiactive)
+ .setPerUidModemModel(
+ BatteryStatsImpl.PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX)
+ .initMeasuredEnergyStatsLocked();
+ BatteryStatsImpl stats = mStatsRule.getBatteryStats();
+
+ // Scan for a cell
+ stats.notePhoneStateLocked(ServiceState.STATE_OUT_OF_SERVICE,
+ TelephonyManager.SIM_STATE_READY,
+ 2000, 2000);
+
+ // Found a cell
+ stats.notePhoneStateLocked(ServiceState.STATE_IN_SERVICE, TelephonyManager.SIM_STATE_READY,
+ 5000, 5000);
+
+ ArrayList<CellSignalStrength> perRatCellStrength = new ArrayList();
+ CellSignalStrength gsmSignalStrength = mock(CellSignalStrength.class);
+ when(gsmSignalStrength.getLevel()).thenReturn(
+ SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
+ perRatCellStrength.add(gsmSignalStrength);
+
+ // Note cell signal strength
+ SignalStrength signalStrength = mock(SignalStrength.class);
+ when(signalStrength.getCellSignalStrengths()).thenReturn(perRatCellStrength);
+ stats.notePhoneSignalStrengthLocked(signalStrength, 5000, 5000);
+
+ stats.noteMobileRadioPowerStateLocked(DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH,
+ 8_000_000_000L, APP_UID, 8000, 8000);
+
+ // Note established network
+ stats.noteNetworkInterfaceForTransports("cellular",
+ new int[]{NetworkCapabilities.TRANSPORT_CELLULAR});
+
+ // Spend some time in each signal strength level. It doesn't matter how long.
+ // The ModemActivityInfo reported level residency should be trusted over the BatteryStats
+ // timers.
+ when(gsmSignalStrength.getLevel()).thenReturn(
+ SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
+ stats.notePhoneSignalStrengthLocked(signalStrength, 8111, 8111);
+ when(gsmSignalStrength.getLevel()).thenReturn(SignalStrength.SIGNAL_STRENGTH_POOR);
+ stats.notePhoneSignalStrengthLocked(signalStrength, 8333, 8333);
+ when(gsmSignalStrength.getLevel()).thenReturn(SignalStrength.SIGNAL_STRENGTH_MODERATE);
+ stats.notePhoneSignalStrengthLocked(signalStrength, 8666, 8666);
+ when(gsmSignalStrength.getLevel()).thenReturn(SignalStrength.SIGNAL_STRENGTH_GOOD);
+ stats.notePhoneSignalStrengthLocked(signalStrength, 9110, 9110);
+
+ stats.noteMobileRadioPowerStateLocked(DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH,
+ 9_500_000_000L, APP_UID2, 9500, 9500);
+
+ when(gsmSignalStrength.getLevel()).thenReturn(SignalStrength.SIGNAL_STRENGTH_GREAT);
+ stats.notePhoneSignalStrengthLocked(signalStrength, 9665, 9665);
+
+ // Note application network activity
+ NetworkStats networkStats = new NetworkStats(10000, 1)
+ .addEntry(new NetworkStats.Entry("cellular", APP_UID, 0, 0,
+ METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 1000, 150, 300, 10, 100))
+ .addEntry(new NetworkStats.Entry("cellular", APP_UID2, 0, 0,
+ METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 500, 50, 2000, 30, 111));
+ mStatsRule.setNetworkStats(networkStats);
+
+ ActivityStatsTechSpecificInfo cdmaInfo = new ActivityStatsTechSpecificInfo(
+ AccessNetwork.CDMA2000, ServiceState.FREQUENCY_RANGE_UNKNOWN,
+ new int[]{10, 11, 12, 13, 14}, 15);
+ ActivityStatsTechSpecificInfo lteInfo = new ActivityStatsTechSpecificInfo(
+ AccessNetwork.EUTRAN, ServiceState.FREQUENCY_RANGE_UNKNOWN,
+ new int[]{20, 21, 22, 23, 24}, 25);
+ ActivityStatsTechSpecificInfo nrLowFreqInfo = new ActivityStatsTechSpecificInfo(
+ AccessNetwork.NGRAN, ServiceState.FREQUENCY_RANGE_LOW,
+ new int[]{30, 31, 32, 33, 34}, 35);
+ ActivityStatsTechSpecificInfo nrMidFreqInfo = new ActivityStatsTechSpecificInfo(
+ AccessNetwork.NGRAN, ServiceState.FREQUENCY_RANGE_MID,
+ new int[]{40, 41, 42, 43, 44}, 45);
+ ActivityStatsTechSpecificInfo nrHighFreqInfo = new ActivityStatsTechSpecificInfo(
+ AccessNetwork.NGRAN, ServiceState.FREQUENCY_RANGE_HIGH,
+ new int[]{50, 51, 52, 53, 54}, 55);
+ ActivityStatsTechSpecificInfo nrMmwaveFreqInfo = new ActivityStatsTechSpecificInfo(
+ AccessNetwork.NGRAN, ServiceState.FREQUENCY_RANGE_MMWAVE,
+ new int[]{60, 61, 62, 63, 64}, 65);
+
+ ActivityStatsTechSpecificInfo[] ratInfos =
+ new ActivityStatsTechSpecificInfo[]{cdmaInfo, lteInfo, nrLowFreqInfo, nrMidFreqInfo,
+ nrHighFreqInfo, nrMmwaveFreqInfo};
+
+ ModemActivityInfo mai = new ModemActivityInfo(10000, 2000, 3000, ratInfos);
+ stats.noteModemControllerActivity(mai, 10_000_000, 10000, 10000,
+ mNetworkStatsManager);
+
+ mStatsRule.setTime(10_000, 10_000);
+
+ MobileRadioPowerCalculator calculator =
+ new MobileRadioPowerCalculator(mStatsRule.getPowerProfile());
+
+ mStatsRule.apply(calculator);
+
+ BatteryConsumer deviceConsumer = mStatsRule.getDeviceBatteryConsumer();
+ assertThat(deviceConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
+ .isWithin(PRECISION).of(2.77778);
+ assertThat(deviceConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION);
+
+ // CDMA2000 [Tx0, Tx1, Tx2, Tx3, Tx4, Rx] drain * duration
+ // [720, 1080, 1440, 1800, 2160, 1440] mA . [10, 11, 12, 13, 14, 15] ms = 111600 mA-ms
+ // LTE [Tx0, Tx1, Tx2, Tx3, Tx4, Rx] drain * duration
+ // [800, 1200, 1600, 2000, 2400, 2000] mA . [20, 21, 22, 23, 24, 25] ms = 230000 mA-ms
+ // 5G Low Frequency [Tx0, Tx1, Tx2, Tx3, Tx4, Rx] drain * duration
+ // (nrFrequency="LOW" values was not defined so fall back to nrFrequency="DEFAULT")
+ // [999, 1333, 1888, 2222, 2666, 2222] mA . [30, 31, 32, 33, 34, 35] ms = 373449 mA-ms
+ // 5G Mid Frequency [Tx0, Tx1, Tx2, Tx3, Tx4, Rx] drain * duration
+ // (nrFrequency="MID" values was not defined so fall back to nrFrequency="DEFAULT")
+ // [999, 1333, 1888, 2222, 2666, 2222] mA . [40, 41, 42, 43, 44, 45] ms = 486749 mA-ms
+ // 5G High Frequency [Tx0, Tx1, Tx2, Tx3, Tx4, Rx] drain * duration
+ // [1818, 2727, 3636, 4545, 5454, 2727] mA . [50, 51, 52, 53, 54, 55] ms = 1104435 mA-ms
+ // 5G Mmwave Frequency [Tx0, Tx1, Tx2, Tx3, Tx4, Rx] drain * duration
+ // [2345, 3456, 4567, 5678, 6789, 3456] mA . [60, 61, 62, 63, 64, 65] ms = 1651520 mA-ms
+ // _________________
+ // = 3957753 mA-ms estimated active consumption
+ //
+ // Idle drain rate * idle duration
+ // 360 mA * 3000 ms = 1080000 mA-ms
+ // Sleep drain rate * sleep duration
+ // 70 mA * 2000 ms = 140000 mA-ms
+ // _________________
+ // = 5177753 mA-ms estimated total consumption
+ //
+ // 2.77778 mA-h measured total consumption * 3957753 / 5177753 = 2.123268 mA-h
+ BatteryConsumer appsConsumer = mStatsRule.getAppsBatteryConsumer();
+ assertThat(appsConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
+ .isWithin(PRECISION).of(2.123268);
+ assertThat(appsConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION);
+
+ // 240 ms Rx Time, 1110 ms Tx Time, 1350 ms active time
+ // 150 App 1 Rx Packets, 10 App 1 Tx packets
+ // 50 App 2 Rx Packets, 30 App 2 Tx packets
+ // 200 total Rx Packets, 40 total Tx packets
+ // 623985 mA-ms Rx consumption, 3333768 mA-ms Tx consumption
+ //
+ // Rx Power consumption * Ratio of App1 / Total Rx Packets:
+ // 623985 * 150 / 200 = 467988.75 mA-ms App 1 Rx Power Consumption
+ //
+ // App 1 Tx Packets + App 1 Rx Packets * Ratio of Tx / Total active time
+ // 10 + 150 * 1110 / 1350 = 133.3333 Estimated App 1 Rx/Tx Packets during Tx
+ // Total Tx Packets + Total Rx Packets * Ratio of Tx / Total active time
+ // 40 + 200 * 1110 / 1350 = 204.44444 Estimated Total Rx/Tx Packets during Tx
+ // Tx Power consumption * Ratio of App 1 / Total Estimated Tx Packets:
+ // 3333768 * 133.33333 / 204.44444 = 2174196.52174 mA-ms App 1 Tx Power Consumption
+ //
+ // Total App Power consumption * Ratio of App 1 / Total Estimated Power Consumption
+ // 2.123268 * (467988.75 + 2174196.52174) / 3957753 = 1.41749 App 1 Power Consumption
+ UidBatteryConsumer uidConsumer = mStatsRule.getUidBatteryConsumer(APP_UID);
+ assertThat(uidConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
+ .isWithin(PRECISION).of(1.41749);
+ assertThat(uidConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION);
+
+ // Rest should go to the other app
+ UidBatteryConsumer uidConsumer2 = mStatsRule.getUidBatteryConsumer(APP_UID2);
+ assertThat(uidConsumer2.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
+ .isWithin(PRECISION).of(0.705778);
+ assertThat(uidConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION);
+ }
+
+ @Test
+ public void testMeasuredEnergyBasedModel_modemActivityInfoRxTxModel_legacyPowerProfile() {
+ mStatsRule.setTestPowerProfile(R.xml.power_profile_test_legacy_modem)
+ .setPerUidModemModel(
+ BatteryStatsImpl.PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX)
+ .initMeasuredEnergyStatsLocked();
+ BatteryStatsImpl stats = mStatsRule.getBatteryStats();
+
+ // Scan for a cell
+ stats.notePhoneStateLocked(ServiceState.STATE_OUT_OF_SERVICE,
+ TelephonyManager.SIM_STATE_READY,
+ 2000, 2000);
+
+ ArrayList<CellSignalStrength> perRatCellStrength = new ArrayList();
+ CellSignalStrength gsmSignalStrength = mock(CellSignalStrength.class);
+ when(gsmSignalStrength.getLevel()).thenReturn(
+ SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
+ perRatCellStrength.add(gsmSignalStrength);
+
+ // Found a cell
+ stats.notePhoneStateLocked(ServiceState.STATE_IN_SERVICE, TelephonyManager.SIM_STATE_READY,
+ 5000, 5000);
+
+ // Note cell signal strength
+ SignalStrength signalStrength = mock(SignalStrength.class);
+ when(signalStrength.getCellSignalStrengths()).thenReturn(perRatCellStrength);
+ stats.notePhoneSignalStrengthLocked(signalStrength, 5000, 5000);
+
+ stats.noteMobileRadioPowerStateLocked(DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH,
+ 8_000_000_000L, APP_UID, 8000, 8000);
+
+ // Note established network
+ stats.noteNetworkInterfaceForTransports("cellular",
+ new int[]{NetworkCapabilities.TRANSPORT_CELLULAR});
+
+ // Spend some time in each signal strength level. It doesn't matter how long.
+ // The ModemActivityInfo reported level residency should be trusted over the BatteryStats
+ // timers.
+ when(gsmSignalStrength.getLevel()).thenReturn(
+ SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
+ stats.notePhoneSignalStrengthLocked(signalStrength, 8111, 8111);
+ when(gsmSignalStrength.getLevel()).thenReturn(SignalStrength.SIGNAL_STRENGTH_POOR);
+ stats.notePhoneSignalStrengthLocked(signalStrength, 8333, 8333);
+ when(gsmSignalStrength.getLevel()).thenReturn(SignalStrength.SIGNAL_STRENGTH_MODERATE);
+ stats.notePhoneSignalStrengthLocked(signalStrength, 8666, 8666);
+ when(gsmSignalStrength.getLevel()).thenReturn(SignalStrength.SIGNAL_STRENGTH_GOOD);
+ stats.notePhoneSignalStrengthLocked(signalStrength, 9110, 9110);
+ when(gsmSignalStrength.getLevel()).thenReturn(SignalStrength.SIGNAL_STRENGTH_GREAT);
+ stats.notePhoneSignalStrengthLocked(signalStrength, 9665, 9665);
+
+ // Note application network activity
+ NetworkStats networkStats = new NetworkStats(10000, 1)
+ .addEntry(new NetworkStats.Entry("cellular", APP_UID, 0, 0,
+ METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 1000, 100, 2000, 20, 100));
+ mStatsRule.setNetworkStats(networkStats);
+
+ ModemActivityInfo mai = new ModemActivityInfo(10000, 2000, 3000,
+ new int[]{100, 200, 300, 400, 500}, 600);
+ stats.noteModemControllerActivity(mai, 10_000_000, 10000, 10000, mNetworkStatsManager);
+
+ mStatsRule.setTime(12_000, 12_000);
+
+ MobileRadioPowerCalculator calculator =
+ new MobileRadioPowerCalculator(mStatsRule.getPowerProfile());
+
+ mStatsRule.apply(calculator);
+
+ BatteryConsumer deviceConsumer = mStatsRule.getDeviceBatteryConsumer();
+ // 10_000_000 micro-Coulomb * 1/1000 milli/micro * 1/3600 hour/second = 2.77778 mAh
+ assertThat(deviceConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
+ .isWithin(PRECISION).of(2.77778);
+ assertThat(deviceConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION);
+
+ BatteryConsumer appsConsumer = mStatsRule.getAppsBatteryConsumer();
+ // Estimated Rx/Tx modem consumption = 0.94 mAh
+ // Estimated total modem consumption = 1.27888 mAh
+ // 2.77778 * 0.94 / 1.27888 = 2.04170 mAh
+ assertThat(appsConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
+ .isWithin(PRECISION).of(2.04170);
+ assertThat(appsConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION);
+
+ UidBatteryConsumer uidConsumer = mStatsRule.getUidBatteryConsumer(APP_UID);
+ assertThat(uidConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
+ .isWithin(PRECISION).of(2.04170);
+ assertThat(uidConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION);
+ }
+
@Test
public void testMeasuredEnergyBasedModel_byProcessState() {
mStatsRule.setTestPowerProfile(R.xml.power_profile_test_legacy_modem)
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/MockBatteryStatsImpl.java b/services/tests/servicestests/src/com/android/server/power/stats/MockBatteryStatsImpl.java
index 19d2639..f803355 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/MockBatteryStatsImpl.java
+++ b/services/tests/servicestests/src/com/android/server/power/stats/MockBatteryStatsImpl.java
@@ -213,6 +213,13 @@
return this;
}
+ @GuardedBy("this")
+ public MockBatteryStatsImpl setPerUidModemModel(int perUidModemModel) {
+ mConstants.PER_UID_MODEM_MODEL = perUidModemModel;
+ mConstants.onChange();
+ return this;
+ }
+
public int getAndClearExternalStatsSyncFlags() {
final int flags = mExternalStatsSync.flags;
mExternalStatsSync.flags = 0;
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/FakeTimeDetectorStrategy.java b/services/tests/servicestests/src/com/android/server/timedetector/FakeTimeDetectorStrategy.java
index 856df359..50040b7 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/FakeTimeDetectorStrategy.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/FakeTimeDetectorStrategy.java
@@ -62,6 +62,15 @@
}
@Override
+ public NetworkTimeSuggestion getLatestNetworkSuggestion() {
+ return null;
+ }
+
+ @Override
+ public void clearLatestNetworkSuggestion() {
+ }
+
+ @Override
public void suggestGnssTime(GnssTimeSuggestion timeSuggestion) {
}
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/NetworkTimeUpdateServiceTest.java b/services/tests/servicestests/src/com/android/server/timedetector/NetworkTimeUpdateServiceTest.java
new file mode 100644
index 0000000..1001422
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/timedetector/NetworkTimeUpdateServiceTest.java
@@ -0,0 +1,678 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.timedetector;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.time.UnixEpochTime;
+import android.net.Network;
+import android.util.NtpTrustedTime;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.server.timedetector.NetworkTimeUpdateService.Engine.RefreshCallbacks;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.net.InetSocketAddress;
+import java.util.function.Supplier;
+
+@RunWith(AndroidJUnit4.class)
+public class NetworkTimeUpdateServiceTest {
+
+ private static final InetSocketAddress FAKE_SERVER_ADDRESS =
+ InetSocketAddress.createUnresolved("test", 123);
+ private static final long ARBITRARY_ELAPSED_REALTIME_MILLIS = 100000000L;
+ private static final long ARBITRARY_UNIX_EPOCH_TIME_MILLIS = 5555555555L;
+ private static final int ARBITRARY_UNCERTAINTY_MILLIS = 999;
+
+ private FakeElapsedRealtimeClock mFakeElapsedRealtimeClock;
+ private NtpTrustedTime mMockNtpTrustedTime;
+ private Network mDummyNetwork;
+
+ @Before
+ public void setUp() {
+ mFakeElapsedRealtimeClock = new FakeElapsedRealtimeClock();
+ mMockNtpTrustedTime = mock(NtpTrustedTime.class);
+ mDummyNetwork = mock(Network.class);
+ }
+
+ @Test
+ public void engineImpl_refreshIfRequiredAndReschedule_success() {
+ mFakeElapsedRealtimeClock.setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS);
+
+ int normalPollingIntervalMillis = 7777777;
+ int shortPollingIntervalMillis = 3333;
+ int tryAgainTimesMax = 5;
+ NetworkTimeUpdateService.Engine engine = new NetworkTimeUpdateService.EngineImpl(
+ mFakeElapsedRealtimeClock,
+ normalPollingIntervalMillis, shortPollingIntervalMillis, tryAgainTimesMax,
+ mMockNtpTrustedTime);
+
+ // Simulated NTP client behavior: No cached time value available initially, then a
+ // successful refresh.
+ NtpTrustedTime.TimeResult timeResult = createNtpTimeResult(
+ mFakeElapsedRealtimeClock.getElapsedRealtimeMillis());
+ when(mMockNtpTrustedTime.getCachedTimeResult()).thenReturn(null, timeResult);
+ when(mMockNtpTrustedTime.forceRefresh(mDummyNetwork)).thenReturn(true);
+
+ // Simulate the passage of time for realism.
+ mFakeElapsedRealtimeClock.incrementMillis(5000);
+
+ RefreshCallbacks mockCallback = mock(RefreshCallbacks.class);
+ // Trigger the engine's logic.
+ engine.refreshIfRequiredAndReschedule(mDummyNetwork, "Test", mockCallback);
+
+ // Expect the refresh attempt to have been made.
+ verify(mMockNtpTrustedTime).forceRefresh(mDummyNetwork);
+
+ // Check everything happened that was supposed to.
+ long expectedDelayMillis = normalPollingIntervalMillis;
+ verify(mockCallback).scheduleNextRefresh(
+ timeResult.getElapsedRealtimeMillis() + expectedDelayMillis);
+
+ NetworkTimeSuggestion expectedSuggestion = createExpectedSuggestion(timeResult);
+ verify(mockCallback).submitSuggestion(expectedSuggestion);
+ }
+
+ @Test
+ public void engineImpl_refreshIfRequiredAndReschedule_failThenFailRepeatedly() {
+ mFakeElapsedRealtimeClock.setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS);
+
+ int normalPollingIntervalMillis = 7777777;
+ int shortPollingIntervalMillis = 3333;
+ int tryAgainTimesMax = 5;
+ NetworkTimeUpdateService.Engine engine = new NetworkTimeUpdateService.EngineImpl(
+ mFakeElapsedRealtimeClock,
+ normalPollingIntervalMillis, shortPollingIntervalMillis, tryAgainTimesMax,
+ mMockNtpTrustedTime);
+
+ for (int i = 0; i < tryAgainTimesMax + 1; i++) {
+ // Simulate the passage of time for realism.
+ mFakeElapsedRealtimeClock.incrementMillis(5000);
+
+ // Simulated NTP client behavior: No cached time value available and failure to refresh.
+ when(mMockNtpTrustedTime.getCachedTimeResult()).thenReturn(null);
+ when(mMockNtpTrustedTime.forceRefresh(mDummyNetwork)).thenReturn(false);
+
+ RefreshCallbacks mockCallback = mock(RefreshCallbacks.class);
+
+ // Trigger the engine's logic.
+ engine.refreshIfRequiredAndReschedule(mDummyNetwork, "Test", mockCallback);
+
+ // Expect a refresh attempt each time: there's no currently cached result.
+ verify(mMockNtpTrustedTime).forceRefresh(mDummyNetwork);
+
+ // Check everything happened that was supposed to.
+ long expectedDelayMillis;
+ if (i < tryAgainTimesMax) {
+ expectedDelayMillis = shortPollingIntervalMillis;
+ } else {
+ expectedDelayMillis = normalPollingIntervalMillis;
+ }
+ verify(mockCallback).scheduleNextRefresh(
+ mFakeElapsedRealtimeClock.getElapsedRealtimeMillis() + expectedDelayMillis);
+ verify(mockCallback, never()).submitSuggestion(any());
+
+ reset(mMockNtpTrustedTime);
+ }
+ }
+
+ @Test
+ public void engineImpl_refreshIfRequiredAndReschedule_successThenFailRepeatedly() {
+ mFakeElapsedRealtimeClock.setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS);
+
+ int normalPollingIntervalMillis = 7777777;
+ int shortPollingIntervalMillis = 3333;
+ int tryAgainTimesMax = 5;
+ NetworkTimeUpdateService.Engine engine = new NetworkTimeUpdateService.EngineImpl(
+ mFakeElapsedRealtimeClock,
+ normalPollingIntervalMillis, shortPollingIntervalMillis, tryAgainTimesMax,
+ mMockNtpTrustedTime);
+
+ NtpTrustedTime.TimeResult timeResult = createNtpTimeResult(
+ mFakeElapsedRealtimeClock.getElapsedRealtimeMillis());
+ NetworkTimeSuggestion expectedSuggestion = createExpectedSuggestion(timeResult);
+
+ {
+ // Simulated NTP client behavior: No cached time value available initially, with a
+ // successful refresh.
+ when(mMockNtpTrustedTime.getCachedTimeResult()).thenReturn(null, timeResult);
+ when(mMockNtpTrustedTime.forceRefresh(mDummyNetwork)).thenReturn(true);
+
+ // Simulate the passage of time for realism.
+ mFakeElapsedRealtimeClock.incrementMillis(5000);
+
+ RefreshCallbacks mockCallback = mock(RefreshCallbacks.class);
+
+ // Trigger the engine's logic.
+ engine.refreshIfRequiredAndReschedule(mDummyNetwork, "Test", mockCallback);
+
+ // Expect the refresh attempt to have been made: there is no cached network time
+ // initially.
+ verify(mMockNtpTrustedTime).forceRefresh(mDummyNetwork);
+
+ long expectedDelayMillis = normalPollingIntervalMillis;
+ verify(mockCallback).scheduleNextRefresh(
+ timeResult.getElapsedRealtimeMillis() + expectedDelayMillis);
+ verify(mockCallback, times(1)).submitSuggestion(expectedSuggestion);
+ reset(mMockNtpTrustedTime);
+ }
+
+ // Increment the current time by enough so that an attempt to refresh the time should be
+ // made every time refreshIfRequiredAndReschedule() is called.
+ mFakeElapsedRealtimeClock.incrementMillis(normalPollingIntervalMillis);
+
+ // Test multiple follow-up calls.
+ for (int i = 0; i < tryAgainTimesMax + 1; i++) {
+ // Simulated NTP client behavior: (Too old) cached time value available, unsuccessful
+ // refresh.
+ when(mMockNtpTrustedTime.getCachedTimeResult()).thenReturn(timeResult);
+ when(mMockNtpTrustedTime.forceRefresh(mDummyNetwork)).thenReturn(false);
+
+ RefreshCallbacks mockCallback = mock(RefreshCallbacks.class);
+
+ // Trigger the engine's logic.
+ engine.refreshIfRequiredAndReschedule(mDummyNetwork, "Test", mockCallback);
+
+ // Expect a refresh attempt each time as the cached network time is too old.
+ verify(mMockNtpTrustedTime).forceRefresh(mDummyNetwork);
+
+ // Check the scheduling.
+ long expectedDelayMillis;
+ if (i < tryAgainTimesMax) {
+ expectedDelayMillis = shortPollingIntervalMillis;
+ } else {
+ expectedDelayMillis = normalPollingIntervalMillis;
+ }
+ verify(mockCallback).scheduleNextRefresh(
+ mFakeElapsedRealtimeClock.getElapsedRealtimeMillis() + expectedDelayMillis);
+
+ // No valid time, no suggestion.
+ verify(mockCallback, never()).submitSuggestion(any());
+
+ reset(mMockNtpTrustedTime);
+
+ // Simulate the passage of time for realism.
+ mFakeElapsedRealtimeClock.incrementMillis(5000);
+ }
+ }
+
+ @Test
+ public void engineImpl_refreshIfRequiredAndReschedule_successThenFail_tryAgainTimesZero() {
+ mFakeElapsedRealtimeClock.setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS);
+
+ int normalPollingIntervalMillis = 7777777;
+ int shortPollingIntervalMillis = 3333;
+ int tryAgainTimesMax = 0;
+ NetworkTimeUpdateService.Engine engine = new NetworkTimeUpdateService.EngineImpl(
+ mFakeElapsedRealtimeClock,
+ normalPollingIntervalMillis, shortPollingIntervalMillis, tryAgainTimesMax,
+ mMockNtpTrustedTime);
+
+ NtpTrustedTime.TimeResult timeResult = createNtpTimeResult(
+ mFakeElapsedRealtimeClock.getElapsedRealtimeMillis());
+ NetworkTimeSuggestion expectedSuggestion = createExpectedSuggestion(timeResult);
+
+ {
+ // Simulated NTP client behavior: No cached time value available initially, with a
+ // successful refresh.
+ when(mMockNtpTrustedTime.getCachedTimeResult()).thenReturn(null, timeResult);
+ when(mMockNtpTrustedTime.forceRefresh(mDummyNetwork)).thenReturn(true);
+
+ // Simulate the passage of time for realism.
+ mFakeElapsedRealtimeClock.incrementMillis(5000);
+
+ RefreshCallbacks mockCallback = mock(RefreshCallbacks.class);
+
+ // Trigger the engine's logic.
+ engine.refreshIfRequiredAndReschedule(mDummyNetwork, "Test", mockCallback);
+
+ // Expect the refresh attempt to have been made: there is no cached network time
+ // initially.
+ verify(mMockNtpTrustedTime).forceRefresh(mDummyNetwork);
+
+ long expectedDelayMillis = normalPollingIntervalMillis;
+ verify(mockCallback).scheduleNextRefresh(
+ timeResult.getElapsedRealtimeMillis() + expectedDelayMillis);
+ verify(mockCallback, times(1)).submitSuggestion(expectedSuggestion);
+ reset(mMockNtpTrustedTime);
+ }
+
+ // Increment the current time by enough so that an attempt to refresh the time should be
+ // made every time refreshIfRequiredAndReschedule() is called.
+ mFakeElapsedRealtimeClock.incrementMillis(normalPollingIntervalMillis);
+
+ // Test multiple follow-up calls.
+ for (int i = 0; i < 3; i++) {
+ // Simulated NTP client behavior: (Too old) cached time value available, unsuccessful
+ // refresh.
+ when(mMockNtpTrustedTime.getCachedTimeResult()).thenReturn(timeResult);
+ when(mMockNtpTrustedTime.forceRefresh(mDummyNetwork)).thenReturn(false);
+
+ RefreshCallbacks mockCallback = mock(RefreshCallbacks.class);
+
+ // Trigger the engine's logic.
+ engine.refreshIfRequiredAndReschedule(mDummyNetwork, "Test", mockCallback);
+
+ // Expect a refresh attempt each time as the cached network time is too old.
+ verify(mMockNtpTrustedTime).forceRefresh(mDummyNetwork);
+
+ // Check the scheduling. tryAgainTimesMax == 0, so the algorithm should start with
+
+ long expectedDelayMillis = normalPollingIntervalMillis;
+ verify(mockCallback).scheduleNextRefresh(
+ mFakeElapsedRealtimeClock.getElapsedRealtimeMillis() + expectedDelayMillis);
+
+ // No valid time, no suggestion.
+ verify(mockCallback, never()).submitSuggestion(any());
+
+ reset(mMockNtpTrustedTime);
+
+ // Simulate the passage of time for realism.
+ mFakeElapsedRealtimeClock.incrementMillis(5000);
+ }
+ }
+
+ @Test
+ public void engineImpl_refreshIfRequiredAndReschedule_successThenFail_tryAgainTimesNegative() {
+ mFakeElapsedRealtimeClock.setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS);
+
+ int normalPollingIntervalMillis = 7777777;
+ int shortPollingIntervalMillis = 3333;
+ int tryAgainTimesMax = -1;
+ NetworkTimeUpdateService.Engine engine = new NetworkTimeUpdateService.EngineImpl(
+ mFakeElapsedRealtimeClock,
+ normalPollingIntervalMillis, shortPollingIntervalMillis, tryAgainTimesMax,
+ mMockNtpTrustedTime);
+
+ NtpTrustedTime.TimeResult timeResult = createNtpTimeResult(
+ mFakeElapsedRealtimeClock.getElapsedRealtimeMillis());
+ NetworkTimeSuggestion expectedSuggestion = createExpectedSuggestion(timeResult);
+
+ {
+ // Simulated NTP client behavior: No cached time value available initially, with a
+ // successful refresh.
+ when(mMockNtpTrustedTime.getCachedTimeResult()).thenReturn(null, timeResult);
+ when(mMockNtpTrustedTime.forceRefresh(mDummyNetwork)).thenReturn(true);
+
+ // Simulate the passage of time for realism.
+ mFakeElapsedRealtimeClock.incrementMillis(5000);
+
+ RefreshCallbacks mockCallback = mock(RefreshCallbacks.class);
+
+ // Trigger the engine's logic.
+ engine.refreshIfRequiredAndReschedule(mDummyNetwork, "Test", mockCallback);
+
+ // Expect the refresh attempt to have been made: there is no cached network time
+ // initially.
+ verify(mMockNtpTrustedTime).forceRefresh(mDummyNetwork);
+
+ long expectedDelayMillis = normalPollingIntervalMillis;
+ verify(mockCallback).scheduleNextRefresh(
+ timeResult.getElapsedRealtimeMillis() + expectedDelayMillis);
+ verify(mockCallback, times(1)).submitSuggestion(expectedSuggestion);
+ reset(mMockNtpTrustedTime);
+ }
+
+ // Increment the current time by enough so that an attempt to refresh the time should be
+ // made every time refreshIfRequiredAndReschedule() is called.
+ mFakeElapsedRealtimeClock.incrementMillis(normalPollingIntervalMillis);
+
+ // Test multiple follow-up calls.
+ for (int i = 0; i < 3; i++) {
+ // Simulated NTP client behavior: (Too old) cached time value available, unsuccessful
+ // refresh.
+ when(mMockNtpTrustedTime.getCachedTimeResult()).thenReturn(timeResult);
+ when(mMockNtpTrustedTime.forceRefresh(mDummyNetwork)).thenReturn(false);
+
+ RefreshCallbacks mockCallback = mock(RefreshCallbacks.class);
+
+ // Trigger the engine's logic.
+ engine.refreshIfRequiredAndReschedule(mDummyNetwork, "Test", mockCallback);
+
+ // Expect a refresh attempt each time as the cached network time is too old.
+ verify(mMockNtpTrustedTime).forceRefresh(mDummyNetwork);
+
+ // Check the scheduling. tryAgainTimesMax == -1, so it should always be
+ // shortPollingIntervalMillis.
+ long expectedDelayMillis = shortPollingIntervalMillis;
+ verify(mockCallback).scheduleNextRefresh(
+ mFakeElapsedRealtimeClock.getElapsedRealtimeMillis() + expectedDelayMillis);
+
+ // No valid time, no suggestion.
+ verify(mockCallback, never()).submitSuggestion(any());
+
+ reset(mMockNtpTrustedTime);
+
+ // Simulate the passage of time for realism.
+ mFakeElapsedRealtimeClock.incrementMillis(5000);
+ }
+ }
+
+ @Test
+ public void engineImpl_refreshIfRequiredAndReschedule_successFailSuccess() {
+ mFakeElapsedRealtimeClock.setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS);
+
+ int normalPollingIntervalMillis = 7777777;
+ int shortPollingIntervalMillis = 3333;
+ int tryAgainTimesMax = 5;
+ NetworkTimeUpdateService.Engine engine = new NetworkTimeUpdateService.EngineImpl(
+ mFakeElapsedRealtimeClock,
+ normalPollingIntervalMillis, shortPollingIntervalMillis, tryAgainTimesMax,
+ mMockNtpTrustedTime);
+
+ NtpTrustedTime.TimeResult timeResult1 = createNtpTimeResult(
+ mFakeElapsedRealtimeClock.getElapsedRealtimeMillis());
+ {
+ // Simulated NTP client behavior: No cached time value available initially, with a
+ // successful refresh.
+ when(mMockNtpTrustedTime.getCachedTimeResult()).thenReturn(null, timeResult1);
+ when(mMockNtpTrustedTime.forceRefresh(mDummyNetwork)).thenReturn(true);
+
+ // Simulate the passage of time for realism.
+ mFakeElapsedRealtimeClock.incrementMillis(5000);
+
+ RefreshCallbacks mockCallback = mock(RefreshCallbacks.class);
+
+ // Trigger the engine's logic.
+ engine.refreshIfRequiredAndReschedule(mDummyNetwork, "Test", mockCallback);
+
+ // Expect the refresh attempt to have been made: there is no cached network time
+ // initially.
+ verify(mMockNtpTrustedTime).forceRefresh(mDummyNetwork);
+
+ long expectedDelayMillis = normalPollingIntervalMillis;
+ verify(mockCallback).scheduleNextRefresh(
+ timeResult1.getElapsedRealtimeMillis() + expectedDelayMillis);
+ NetworkTimeSuggestion expectedSuggestion = createExpectedSuggestion(timeResult1);
+ verify(mockCallback, times(1)).submitSuggestion(expectedSuggestion);
+ reset(mMockNtpTrustedTime);
+ }
+
+ // Increment the current time by enough so that the cached time result is too old and an
+ // attempt to refresh the time should be made every time refreshIfRequiredAndReschedule() is
+ // called.
+ mFakeElapsedRealtimeClock.incrementMillis(normalPollingIntervalMillis);
+
+ {
+ // Simulated NTP client behavior: (Old) cached time value available initially, with an
+ // unsuccessful refresh.
+ when(mMockNtpTrustedTime.getCachedTimeResult()).thenReturn(timeResult1);
+ when(mMockNtpTrustedTime.forceRefresh(mDummyNetwork)).thenReturn(false);
+
+ RefreshCallbacks mockCallback = mock(RefreshCallbacks.class);
+
+ // Trigger the engine's logic.
+ engine.refreshIfRequiredAndReschedule(mDummyNetwork, "Test", mockCallback);
+
+ // Expect the refresh attempt to have been made: the timeResult is too old.
+ verify(mMockNtpTrustedTime).forceRefresh(mDummyNetwork);
+
+ long expectedDelayMillis = shortPollingIntervalMillis;
+ verify(mockCallback).scheduleNextRefresh(
+ mFakeElapsedRealtimeClock.getElapsedRealtimeMillis() + expectedDelayMillis);
+
+ // No valid time, no suggestion.
+ verify(mockCallback, never()).submitSuggestion(any());
+ reset(mMockNtpTrustedTime);
+ }
+
+ // Increment time enough to avoid the minimum refresh interval protection.
+ mFakeElapsedRealtimeClock.incrementMillis(shortPollingIntervalMillis);
+
+ NtpTrustedTime.TimeResult timeResult2 = createNtpTimeResult(
+ mFakeElapsedRealtimeClock.getElapsedRealtimeMillis());
+
+ {
+ // Simulated NTP client behavior: (Old) cached time value available initially, with a
+ // successful refresh and a new cached time value.
+ when(mMockNtpTrustedTime.getCachedTimeResult()).thenReturn(timeResult1, timeResult2);
+ when(mMockNtpTrustedTime.forceRefresh(mDummyNetwork)).thenReturn(true);
+
+ // Simulate the passage of time for realism.
+ mFakeElapsedRealtimeClock.incrementMillis(5000);
+
+ RefreshCallbacks mockCallback = mock(RefreshCallbacks.class);
+
+ // Trigger the engine's logic.
+ engine.refreshIfRequiredAndReschedule(mDummyNetwork, "Test", mockCallback);
+
+ // Expect the refresh attempt to have been made: the timeResult is too old.
+ verify(mMockNtpTrustedTime).forceRefresh(mDummyNetwork);
+
+ long expectedDelayMillis = normalPollingIntervalMillis;
+ verify(mockCallback).scheduleNextRefresh(
+ timeResult2.getElapsedRealtimeMillis() + expectedDelayMillis);
+ NetworkTimeSuggestion expectedSuggestion = createExpectedSuggestion(timeResult2);
+ verify(mockCallback, times(1)).submitSuggestion(expectedSuggestion);
+ reset(mMockNtpTrustedTime);
+ }
+ }
+
+ /**
+ * Confirms that if a refreshIfRequiredAndReschedule() call is made, e.g. for reasons besides
+ * scheduled alerts, and the latest time is not too old, then an NTP refresh won't be attempted.
+ * A suggestion will still be made.
+ */
+ @Test
+ public void engineImpl_refreshIfRequiredAndReschedule_noRefreshIfLatestIsFresh() {
+ mFakeElapsedRealtimeClock.setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS);
+
+ int normalPollingIntervalMillis = 7777777;
+ int shortPollingIntervalMillis = 3333;
+ int tryAgainTimesMax = 5;
+ NetworkTimeUpdateService.Engine engine = new NetworkTimeUpdateService.EngineImpl(
+ mFakeElapsedRealtimeClock,
+ normalPollingIntervalMillis, shortPollingIntervalMillis, tryAgainTimesMax,
+ mMockNtpTrustedTime);
+
+ // Simulated NTP client behavior: A cached time value is available.
+ NtpTrustedTime.TimeResult timeResult = createNtpTimeResult(
+ mFakeElapsedRealtimeClock.getElapsedRealtimeMillis());
+ when(mMockNtpTrustedTime.getCachedTimeResult()).thenReturn(timeResult);
+ // Increment the clock, but not enough to consider the cached value too old.
+ mFakeElapsedRealtimeClock.incrementMillis(normalPollingIntervalMillis - 1);
+
+ RefreshCallbacks mockCallback = mock(RefreshCallbacks.class);
+ // Trigger the engine's logic.
+ engine.refreshIfRequiredAndReschedule(mDummyNetwork, "Test", mockCallback);
+
+ // Expect no refresh attempt to have been made.
+ verify(mMockNtpTrustedTime, never()).forceRefresh(any());
+
+ // The next wake-up should be rescheduled for when the cached time value will become too
+ // old.
+ long expectedDelayMillis = normalPollingIntervalMillis;
+ verify(mockCallback).scheduleNextRefresh(
+ timeResult.getElapsedRealtimeMillis() + expectedDelayMillis);
+
+ // Suggestions must be made every time if the cached time value is not too old in case it
+ // was refreshed by a different component.
+ NetworkTimeSuggestion expectedSuggestion = createExpectedSuggestion(timeResult);
+ verify(mockCallback, times(1)).submitSuggestion(expectedSuggestion);
+ }
+
+ /**
+ * Confirms that if a refreshIfRequiredAndReschedule() call is made, e.g. for reasons besides
+ * scheduled alerts, and the latest time is too old, then an NTP refresh will be attempted.
+ */
+ @Test
+ public void engineImpl_refreshIfRequiredAndReschedule_failureHandlingAfterLatestIsTooOld() {
+ mFakeElapsedRealtimeClock.setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS);
+
+ int normalPollingIntervalMillis = 7777777;
+ int shortPollingIntervalMillis = 3333;
+ int tryAgainTimesMax = 5;
+ NetworkTimeUpdateService.Engine engine = new NetworkTimeUpdateService.EngineImpl(
+ mFakeElapsedRealtimeClock,
+ normalPollingIntervalMillis, shortPollingIntervalMillis, tryAgainTimesMax,
+ mMockNtpTrustedTime);
+
+ // Simulated NTP client behavior: A cached time value is available, increment the clock,
+ // enough to consider the cached value too old. The refresh attempt will fail.
+ NtpTrustedTime.TimeResult timeResult = createNtpTimeResult(
+ mFakeElapsedRealtimeClock.getElapsedRealtimeMillis());
+ when(mMockNtpTrustedTime.getCachedTimeResult()).thenReturn(timeResult);
+ mFakeElapsedRealtimeClock.incrementMillis(normalPollingIntervalMillis);
+ when(mMockNtpTrustedTime.forceRefresh(mDummyNetwork)).thenReturn(false);
+
+ RefreshCallbacks mockCallback = mock(RefreshCallbacks.class);
+ // Trigger the engine's logic.
+ engine.refreshIfRequiredAndReschedule(mDummyNetwork, "Test", mockCallback);
+
+ // Expect a refresh attempt to have been made.
+ verify(mMockNtpTrustedTime, times(1)).forceRefresh(mDummyNetwork);
+
+ // The next wake-up should be rescheduled using the short polling interval.
+ long expectedDelayMillis = shortPollingIntervalMillis;
+ verify(mockCallback).scheduleNextRefresh(
+ mFakeElapsedRealtimeClock.getElapsedRealtimeMillis() + expectedDelayMillis);
+
+ // Suggestions should not be made if the cached time value is too old.
+ verify(mockCallback, never()).submitSuggestion(any());
+ }
+
+ /**
+ * Confirms that if a refreshIfRequiredAndReschedule() call is made and there was a recently
+ * failed refresh, then another won't be scheduled too soon.
+ */
+ @Test
+ public void engineImpl_refreshIfRequiredAndReschedule_minimumRefreshTimeEnforced() {
+ mFakeElapsedRealtimeClock.setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS);
+
+ int normalPollingIntervalMillis = 7777777;
+ int shortPollingIntervalMillis = 3333;
+ int tryAgainTimesMax = 0;
+ NetworkTimeUpdateService.Engine engine = new NetworkTimeUpdateService.EngineImpl(
+ mFakeElapsedRealtimeClock,
+ normalPollingIntervalMillis, shortPollingIntervalMillis, tryAgainTimesMax,
+ mMockNtpTrustedTime);
+
+ NtpTrustedTime.TimeResult timeResult = createNtpTimeResult(
+ mFakeElapsedRealtimeClock.getElapsedRealtimeMillis());
+
+ // Simulate an initial call to refreshIfRequiredAndReschedule() prime the "last refresh
+ // attempt" time. A cached time value is available, but it's too old but the refresh
+ // attempt will fail.
+ long lastRefreshAttemptElapsedMillis;
+ {
+ // Increment the clock, enough to consider the cached value too old.
+ mFakeElapsedRealtimeClock.incrementMillis(normalPollingIntervalMillis);
+ when(mMockNtpTrustedTime.getCachedTimeResult()).thenReturn(timeResult);
+ when(mMockNtpTrustedTime.forceRefresh(mDummyNetwork)).thenReturn(false);
+
+ RefreshCallbacks mockCallback = mock(RefreshCallbacks.class);
+ // Trigger the engine's logic.
+ engine.refreshIfRequiredAndReschedule(mDummyNetwork, "Test", mockCallback);
+
+ // Expect a refresh attempt to have been made.
+ verify(mMockNtpTrustedTime, times(1)).forceRefresh(mDummyNetwork);
+ lastRefreshAttemptElapsedMillis = mFakeElapsedRealtimeClock.getElapsedRealtimeMillis();
+
+ // The next wake-up should be rescheduled using the normalPollingIntervalMillis.
+ // Because the time signal age > normalPollingIntervalMillis, the last refresh attempt
+ // time will be used.
+ long expectedDelayMillis = normalPollingIntervalMillis;
+ long expectedNextRefreshElapsedMillis =
+ lastRefreshAttemptElapsedMillis + expectedDelayMillis;
+ verify(mockCallback).scheduleNextRefresh(expectedNextRefreshElapsedMillis);
+
+ // Suggestions should not be made if the cached time value is too old.
+ verify(mockCallback, never()).submitSuggestion(any());
+
+ reset(mMockNtpTrustedTime);
+ }
+
+ // Simulate a second call to refreshIfRequiredAndReschedule() very soon after the first, as
+ // might happen if there were a network state change.
+ // The cached time value is available, but it's still too old. Because the last call was so
+ // recent, no refresh should take place and the next scheduled refresh time should be
+ // set appropriately based on the last attempt.
+ {
+ // Increment the clock by a relatively small amount so that it's considered "too soon".
+ mFakeElapsedRealtimeClock.incrementMillis(shortPollingIntervalMillis / 2);
+
+ when(mMockNtpTrustedTime.getCachedTimeResult()).thenReturn(timeResult);
+
+ RefreshCallbacks mockCallback = mock(RefreshCallbacks.class);
+ // Trigger the engine's logic.
+ engine.refreshIfRequiredAndReschedule(mDummyNetwork, "Test", mockCallback);
+
+ // Expect no refresh attempt to have been made: time elapsed isn't enough.
+ verify(mMockNtpTrustedTime, never()).forceRefresh(any());
+
+ // The next wake-up should be rescheduled using the normal polling interval and the last
+ // refresh attempt time.
+ long expectedDelayMillis = normalPollingIntervalMillis;
+ long expectedNextRefreshElapsedMillis =
+ lastRefreshAttemptElapsedMillis + expectedDelayMillis;
+ verify(mockCallback).scheduleNextRefresh(expectedNextRefreshElapsedMillis);
+
+ // Suggestions should not be made if the cached time value is too old.
+ verify(mockCallback, never()).submitSuggestion(any());
+
+ reset(mMockNtpTrustedTime);
+ }
+ }
+
+ private static NetworkTimeSuggestion createExpectedSuggestion(
+ NtpTrustedTime.TimeResult timeResult) {
+ UnixEpochTime unixEpochTime = new UnixEpochTime(
+ timeResult.getElapsedRealtimeMillis(), timeResult.getTimeMillis());
+ return new NetworkTimeSuggestion(unixEpochTime, timeResult.getUncertaintyMillis());
+ }
+
+ private static NtpTrustedTime.TimeResult createNtpTimeResult(long elapsedRealtimeMillis) {
+ return new NtpTrustedTime.TimeResult(
+ ARBITRARY_UNIX_EPOCH_TIME_MILLIS,
+ elapsedRealtimeMillis,
+ ARBITRARY_UNCERTAINTY_MILLIS,
+ FAKE_SERVER_ADDRESS);
+ }
+
+ private static class FakeElapsedRealtimeClock implements Supplier<Long> {
+
+ private long mElapsedRealtimeMillis;
+
+ public void setElapsedRealtimeMillis(long elapsedRealtimeMillis) {
+ mElapsedRealtimeMillis = elapsedRealtimeMillis;
+ }
+
+ public long getElapsedRealtimeMillis() {
+ return mElapsedRealtimeMillis;
+ }
+
+ public long incrementMillis(int millis) {
+ mElapsedRealtimeMillis += millis;
+ return mElapsedRealtimeMillis;
+ }
+
+ @Override
+ public Long get() {
+ return getElapsedRealtimeMillis();
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
index a857238..0b339ad 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
@@ -380,6 +380,28 @@
}
@Test
+ public void testClearNetworkTime_withoutPermission() {
+ doThrow(new SecurityException("Mock"))
+ .when(mMockContext).enforceCallingPermission(anyString(), any());
+
+ assertThrows(SecurityException.class,
+ () -> mTimeDetectorService.clearNetworkTime());
+ verify(mMockContext).enforceCallingPermission(
+ eq(android.Manifest.permission.SET_TIME), anyString());
+ }
+
+ @Test
+ public void testClearNetworkTime() throws Exception {
+ doNothing().when(mMockContext).enforceCallingPermission(anyString(), any());
+
+ mTimeDetectorService.clearNetworkTime();
+
+ verify(mMockContext).enforceCallingPermission(
+ eq(android.Manifest.permission.SET_TIME), anyString());
+ verify(mFakeTimeDetectorStrategySpy).clearLatestNetworkSuggestion();
+ }
+
+ @Test
public void testLatestNetworkTime() {
NtpTrustedTime.TimeResult latestNetworkTime = new NtpTrustedTime.TimeResult(
1234L, 54321L, 999, InetSocketAddress.createUnresolved("test.timeserver", 123));
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
index caef494..37da2a2 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
@@ -874,6 +874,7 @@
long expectedSystemClockMillis =
script.calculateTimeInMillisForNow(timeSuggestion.getUnixEpochTime());
script.simulateNetworkTimeSuggestion(timeSuggestion)
+ .assertLatestNetworkSuggestion(timeSuggestion)
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis);
}
@@ -891,10 +892,55 @@
script.simulateTimePassing()
.simulateNetworkTimeSuggestion(timeSuggestion)
+ .assertLatestNetworkSuggestion(timeSuggestion)
.verifySystemClockWasNotSetAndResetCallTracking();
}
@Test
+ public void testClearLatestNetworkSuggestion() {
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+ .setOriginPriorities(ORIGIN_NETWORK, ORIGIN_EXTERNAL)
+ .build();
+ Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+ // Create two different time suggestions for the current elapsedRealtimeMillis.
+ ExternalTimeSuggestion externalTimeSuggestion =
+ script.generateExternalTimeSuggestion(ARBITRARY_TEST_TIME);
+ NetworkTimeSuggestion networkTimeSuggestion =
+ script.generateNetworkTimeSuggestion(ARBITRARY_TEST_TIME.plus(Duration.ofHours(5)));
+ script.simulateTimePassing();
+
+ // Suggest an external time: This should cause the device to change time.
+ {
+ long expectedSystemClockMillis =
+ script.calculateTimeInMillisForNow(externalTimeSuggestion.getUnixEpochTime());
+ script.simulateExternalTimeSuggestion(externalTimeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis);
+ }
+
+ // Suggest a network time: This should cause the device to change time because
+ // network > external.
+ {
+ long expectedSystemClockMillis =
+ script.calculateTimeInMillisForNow(networkTimeSuggestion.getUnixEpochTime());
+ script.simulateNetworkTimeSuggestion(networkTimeSuggestion)
+ .assertLatestNetworkSuggestion(networkTimeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis);
+ }
+
+ // Clear the network time. This should cause the device to change back to the external time,
+ // which is now the best time available.
+ {
+ long expectedSystemClockMillis =
+ script.calculateTimeInMillisForNow(externalTimeSuggestion.getUnixEpochTime());
+ script.simulateClearLatestNetworkSuggestion()
+ .assertLatestNetworkSuggestion(null)
+ .verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis);
+ }
+ }
+
+ @Test
public void testSuggestNetworkTime_rejectedBelowLowerBound() {
ConfigurationInternal configInternal =
new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
@@ -908,6 +954,7 @@
NetworkTimeSuggestion timeSuggestion =
script.generateNetworkTimeSuggestion(belowLowerBound);
script.simulateNetworkTimeSuggestion(timeSuggestion)
+ .assertLatestNetworkSuggestion(null)
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW)
.verifySystemClockWasNotSetAndResetCallTracking();
}
@@ -926,6 +973,7 @@
NetworkTimeSuggestion timeSuggestion =
script.generateNetworkTimeSuggestion(aboveLowerBound);
script.simulateNetworkTimeSuggestion(timeSuggestion)
+ .assertLatestNetworkSuggestion(timeSuggestion)
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
.verifySystemClockWasSetAndResetCallTracking(aboveLowerBound.toEpochMilli());
}
@@ -944,6 +992,7 @@
NetworkTimeSuggestion timeSuggestion =
script.generateNetworkTimeSuggestion(aboveUpperBound);
script.simulateNetworkTimeSuggestion(timeSuggestion)
+ .assertLatestNetworkSuggestion(null)
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW)
.verifySystemClockWasNotSetAndResetCallTracking();
}
@@ -962,6 +1011,7 @@
NetworkTimeSuggestion timeSuggestion =
script.generateNetworkTimeSuggestion(belowUpperBound);
script.simulateNetworkTimeSuggestion(timeSuggestion)
+ .assertLatestNetworkSuggestion(timeSuggestion)
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
.verifySystemClockWasSetAndResetCallTracking(belowUpperBound.toEpochMilli());
}
@@ -1745,7 +1795,7 @@
}
@Test
- public void suggestionsFromNetworkOriginNotInPriorityList_areIgnored() {
+ public void suggestionsFromNetworkOriginNotInPriorityList_areNotUsed() {
ConfigurationInternal configInternal =
new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
.setOriginPriorities(ORIGIN_TELEPHONY)
@@ -1757,11 +1807,12 @@
script.simulateNetworkTimeSuggestion(timeSuggestion)
.assertLatestNetworkSuggestion(timeSuggestion)
+ .assertLatestNetworkSuggestion(timeSuggestion)
.verifySystemClockWasNotSetAndResetCallTracking();
}
@Test
- public void suggestionsFromGnssOriginNotInPriorityList_areIgnored() {
+ public void suggestionsFromGnssOriginNotInPriorityList_areNotUsed() {
ConfigurationInternal configInternal =
new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
.setOriginPriorities(ORIGIN_TELEPHONY)
@@ -1777,7 +1828,7 @@
}
@Test
- public void suggestionsFromExternalOriginNotInPriorityList_areIgnored() {
+ public void suggestionsFromExternalOriginNotInPriorityList_areNotUsed() {
ConfigurationInternal configInternal =
new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
.setOriginPriorities(ORIGIN_TELEPHONY)
@@ -2015,6 +2066,11 @@
return this;
}
+ Script simulateClearLatestNetworkSuggestion() {
+ mTimeDetectorStrategy.clearLatestNetworkSuggestion();
+ return this;
+ }
+
Script simulateGnssTimeSuggestion(GnssTimeSuggestion timeSuggestion) {
mTimeDetectorStrategy.suggestGnssTime(timeSuggestion);
return this;
@@ -2056,6 +2112,12 @@
return this;
}
+ /** Calls {@link TimeDetectorStrategy#confirmTime(UnixEpochTime)}. */
+ Script simulateConfirmTime(UnixEpochTime confirmationTime, boolean expectedReturnValue) {
+ assertEquals(expectedReturnValue, mTimeDetectorStrategy.confirmTime(confirmationTime));
+ return this;
+ }
+
Script verifySystemClockWasNotSetAndResetCallTracking() {
mFakeEnvironment.verifySystemClockNotSet();
mFakeEnvironment.resetCallTracking();
@@ -2218,11 +2280,6 @@
long calculateTimeInMillisForNow(UnixEpochTime unixEpochTime) {
return unixEpochTime.at(peekElapsedRealtimeMillis()).getUnixEpochTimeMillis();
}
-
- Script simulateConfirmTime(UnixEpochTime confirmationTime, boolean expectedReturnValue) {
- assertEquals(expectedReturnValue, mTimeDetectorStrategy.confirmTime(confirmationTime));
- return this;
- }
}
private static TelephonyTimeSuggestion createTelephonyTimeSuggestion(int slotIndex,
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index d54d1fe..5f8a2b5 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -839,7 +839,8 @@
.setName("bubblebot")
.build();
RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
- PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(),
+ PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0,
+ new Intent().setPackage(mContext.getPackageName()),
PendingIntent.FLAG_MUTABLE);
Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
@@ -9227,7 +9228,8 @@
NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
ArrayList<Notification.Action> extraAction = new ArrayList<>();
RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
- PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(),
+ PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0,
+ new Intent().setPackage(mContext.getPackageName()),
PendingIntent.FLAG_MUTABLE);
Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
diff --git a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
index a76b82b..fd1ca68 100644
--- a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
+++ b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
@@ -407,7 +407,7 @@
void assertShowRecentApps() {
waitForIdle();
- verify(mStatusBarManagerInternal).showRecentApps(anyBoolean());
+ verify(mStatusBarManagerInternal).showRecentApps(anyBoolean(), anyBoolean());
}
void assertSwitchKeyboardLayout() {
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 4ee87d4..e02863e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -58,6 +58,7 @@
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN;
import static android.view.WindowManager.TRANSIT_PIP;
@@ -3143,46 +3144,6 @@
assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));
}
- @Test
- public void testImeInsetsFrozenFlag_resetWhenReparented() {
- final ActivityRecord activity = createActivityWithTask();
- final WindowState app = createWindow(null, TYPE_APPLICATION, activity, "app");
- final WindowState imeWindow = createWindow(null, TYPE_APPLICATION, "imeWindow");
- final Task newTask = new TaskBuilder(mSupervisor).build();
- makeWindowVisible(app, imeWindow);
- mDisplayContent.mInputMethodWindow = imeWindow;
- mDisplayContent.setImeLayeringTarget(app);
- mDisplayContent.setImeInputTarget(app);
-
- // Simulate app is closing and expect the last IME is shown and IME insets is frozen.
- app.mActivityRecord.commitVisibility(false, false);
- assertTrue(app.mActivityRecord.mLastImeShown);
- assertTrue(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
-
- // Expect IME insets frozen state will reset when the activity is reparent to the new task.
- activity.setState(RESUMED, "test");
- activity.reparent(newTask, 0 /* top */, "test");
- assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
- }
-
- @SetupWindows(addWindows = W_INPUT_METHOD)
- @Test
- public void testImeInsetsFrozenFlag_resetWhenResized() {
- final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
- makeWindowVisibleAndDrawn(app, mImeWindow);
- mDisplayContent.setImeLayeringTarget(app);
- mDisplayContent.setImeInputTarget(app);
-
- // Simulate app is closing and expect the last IME is shown and IME insets is frozen.
- app.mActivityRecord.commitVisibility(false, false);
- assertTrue(app.mActivityRecord.mLastImeShown);
- assertTrue(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
-
- // Expect IME insets frozen state will reset when the activity is reparent to the new task.
- app.mActivityRecord.onResize();
- assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
- }
-
@SetupWindows(addWindows = W_INPUT_METHOD)
@Test
public void testImeInsetsFrozenFlag_resetWhenNoImeFocusableInActivity() {
@@ -3216,6 +3177,10 @@
public void testImeInsetsFrozenFlag_resetWhenReportedToBeImeInputTarget() {
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
+ mDisplayContent.getInsetsStateController().getSourceProvider(ITYPE_IME).setWindowContainer(
+ mImeWindow, null, null);
+ mImeWindow.getControllableInsetProvider().setServerVisible(true);
+
InsetsSource imeSource = new InsetsSource(ITYPE_IME, ime());
app.mAboveInsetsState.addSource(imeSource);
mDisplayContent.setImeLayeringTarget(app);
@@ -3233,8 +3198,10 @@
// Simulate app re-start input or turning screen off/on then unlocked by un-secure
// keyguard to back to the app, expect IME insets is not frozen
- mDisplayContent.updateImeInputAndControlTarget(app);
app.mActivityRecord.commitVisibility(true, false);
+ mDisplayContent.updateImeInputAndControlTarget(app);
+ mDisplayContent.mWmService.mRoot.performSurfacePlacement();
+
assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
imeSource.setVisible(true);
@@ -3274,12 +3241,12 @@
assertTrue(app2.mActivityRecord.mImeInsetsFrozenUntilStartInput);
// Simulate switching to app2 to make it visible to be IME targets.
- makeWindowVisibleAndDrawn(app2);
spyOn(app2);
spyOn(app2.mClient);
ArgumentCaptor<InsetsState> insetsStateCaptor = ArgumentCaptor.forClass(InsetsState.class);
doReturn(true).when(app2).isReadyToDispatchInsetsState();
mDisplayContent.setImeLayeringTarget(app2);
+ app2.mActivityRecord.commitVisibility(true, false);
mDisplayContent.updateImeInputAndControlTarget(app2);
mDisplayContent.mWmService.mRoot.performSurfacePlacement();
@@ -3293,6 +3260,57 @@
}
@Test
+ public void testImeInsetsFrozenFlag_multiWindowActivities() {
+ final WindowToken imeToken = createTestWindowToken(TYPE_INPUT_METHOD, mDisplayContent);
+ final WindowState ime = createWindow(null, TYPE_INPUT_METHOD, imeToken, "ime");
+ makeWindowVisibleAndDrawn(ime);
+
+ // Create a split-screen root task with activity1 and activity 2.
+ final Task task = new TaskBuilder(mSupervisor)
+ .setCreateParentTask(true).setCreateActivity(true).build();
+ task.getRootTask().setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
+ final ActivityRecord activity1 = task.getTopNonFinishingActivity();
+ activity1.getTask().setResumedActivity(activity1, "testApp1");
+
+ final ActivityRecord activity2 = new TaskBuilder(mSupervisor)
+ .setWindowingMode(WINDOWING_MODE_MULTI_WINDOW)
+ .setCreateActivity(true).build().getTopMostActivity();
+ activity2.getTask().setResumedActivity(activity2, "testApp2");
+ activity2.getTask().setParent(task.getRootTask());
+
+ // Simulate activity1 and activity2 both have set mImeInsetsFrozenUntilStartInput when
+ // invisible to user.
+ activity1.mImeInsetsFrozenUntilStartInput = true;
+ activity2.mImeInsetsFrozenUntilStartInput = true;
+
+ final WindowState app1 = createWindow(null, TYPE_APPLICATION, activity1, "app1");
+ final WindowState app2 = createWindow(null, TYPE_APPLICATION, activity2, "app2");
+ makeWindowVisibleAndDrawn(app1, app2);
+
+ final InsetsStateController controller = mDisplayContent.getInsetsStateController();
+ controller.getSourceProvider(ITYPE_IME).setWindowContainer(
+ ime, null, null);
+ ime.getControllableInsetProvider().setServerVisible(true);
+
+ // app1 starts input and expect IME insets for all activities in split-screen will be
+ // frozen until the input started.
+ mDisplayContent.setImeLayeringTarget(app1);
+ mDisplayContent.updateImeInputAndControlTarget(app1);
+ mDisplayContent.mWmService.mRoot.performSurfacePlacement();
+
+ assertEquals(app1, mDisplayContent.getImeInputTarget());
+ assertFalse(activity1.mImeInsetsFrozenUntilStartInput);
+ assertFalse(activity2.mImeInsetsFrozenUntilStartInput);
+
+ app1.setRequestedVisibleTypes(ime());
+ controller.onInsetsModified(app1);
+
+ // Expect all activities in split-screen will get IME insets visible state
+ assertTrue(app1.getInsetsState().peekSource(ITYPE_IME).isVisible());
+ assertTrue(app2.getInsetsState().peekSource(ITYPE_IME).isVisible());
+ }
+
+ @Test
public void testInClosingAnimation_visibilityNotCommitted_doNotHideSurface() {
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
makeWindowVisibleAndDrawn(app);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ContentRecorderTests.java b/services/tests/wmtests/src/com/android/server/wm/ContentRecorderTests.java
index 4ad8516..8cc362c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ContentRecorderTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ContentRecorderTests.java
@@ -280,7 +280,7 @@
}
@Test
- public void testStartRecording_notifiesCallback() {
+ public void testStartRecording_notifiesCallback_taskSession() {
// WHEN a recording is ongoing.
mContentRecorder.setContentRecordingSession(mTaskSession);
mContentRecorder.updateRecording();
@@ -292,6 +292,18 @@
}
@Test
+ public void testStartRecording_notifiesCallback_displaySession() {
+ // WHEN a recording is ongoing.
+ mContentRecorder.setContentRecordingSession(mDisplaySession);
+ mContentRecorder.updateRecording();
+ assertThat(mContentRecorder.isCurrentlyRecording()).isTrue();
+
+ // THEN the visibility change callback is notified.
+ verify(mMediaProjectionManagerWrapper)
+ .notifyActiveProjectionCapturedContentVisibilityChanged(true);
+ }
+
+ @Test
public void testOnVisibleRequestedChanged_notifiesCallback() {
// WHEN a recording is ongoing.
mContentRecorder.setContentRecordingSession(mTaskSession);
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index 113f5ec..352e498 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -201,27 +201,6 @@
}
@Test
- public void testNotApplyStrategyToTranslucentActivitiesWithDifferentUid() {
- mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true);
- setUpDisplaySizeWithApp(2000, 1000);
- prepareUnresizable(mActivity, 1.5f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT);
- mActivity.info.setMinAspectRatio(1.2f);
- mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
- // Translucent Activity
- final ActivityRecord translucentActivity = new ActivityBuilder(mAtm)
- .setScreenOrientation(SCREEN_ORIENTATION_LANDSCAPE)
- .setMinAspectRatio(1.1f)
- .setMaxAspectRatio(3f)
- .build();
- doReturn(false).when(translucentActivity).fillsParent();
- mTask.addChild(translucentActivity);
- // We check bounds
- final Rect opaqueBounds = mActivity.getConfiguration().windowConfiguration.getBounds();
- final Rect translucentRequestedBounds = translucentActivity.getRequestedOverrideBounds();
- assertNotEquals(opaqueBounds, translucentRequestedBounds);
- }
-
- @Test
public void testApplyStrategyToMultipleTranslucentActivities() {
mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true);
setUpDisplaySizeWithApp(2000, 1000);
@@ -295,6 +274,15 @@
assertEquals(RESTARTING_PROCESS, mActivity.getState());
assertNotEquals(originalOverrideBounds, mActivity.getBounds());
+
+ // Even if the state is changed (e.g. a floating activity on top is finished and make it
+ // resume), the restart procedure should recover the state and continue to kill the process.
+ mActivity.setState(RESUMED, "anyStateChange");
+ doReturn(true).when(mSupervisor).hasScheduledRestartTimeouts(mActivity);
+ mAtm.mActivityClientController.activityStopped(mActivity.token, null /* icicle */,
+ null /* persistentState */, null /* description */);
+ assertEquals(RESTARTING_PROCESS, mActivity.getState());
+ verify(mSupervisor).removeRestartTimeouts(mActivity);
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
index a405e5a..dbd7a4b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
@@ -545,6 +545,7 @@
mTransaction.reparentActivityToTaskFragment(mFragmentToken, mock(IBinder.class));
mTransaction.setAdjacentTaskFragments(mFragmentToken, mock(IBinder.class),
null /* options */);
+ mTransaction.clearAdjacentTaskFragments(mFragmentToken);
assertApplyTransactionAllowed(mTransaction);
// Successfully created a TaskFragment.
@@ -619,12 +620,16 @@
// Not allowed because TaskFragments are not organized by the caller organizer.
assertApplyTransactionDisallowed(mTransaction);
+ assertNull(mTaskFragment.getAdjacentTaskFragment());
+ assertNull(taskFragment2.getAdjacentTaskFragment());
mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* uid */,
"Test:TaskFragmentOrganizer" /* processName */);
// Not allowed because TaskFragment2 is not organized by the caller organizer.
assertApplyTransactionDisallowed(mTransaction);
+ assertNull(mTaskFragment.getAdjacentTaskFragment());
+ assertNull(taskFragment2.getAdjacentTaskFragment());
mTaskFragment.onTaskFragmentOrganizerRemoved();
taskFragment2.setTaskFragmentOrganizer(mOrganizerToken, 10 /* uid */,
@@ -632,11 +637,46 @@
// Not allowed because mTaskFragment is not organized by the caller organizer.
assertApplyTransactionDisallowed(mTransaction);
+ assertNull(mTaskFragment.getAdjacentTaskFragment());
+ assertNull(taskFragment2.getAdjacentTaskFragment());
mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* uid */,
"Test:TaskFragmentOrganizer" /* processName */);
assertApplyTransactionAllowed(mTransaction);
+ assertEquals(taskFragment2, mTaskFragment.getAdjacentTaskFragment());
+ }
+
+ @Test
+ public void testApplyTransaction_enforceTaskFragmentOrganized_clearAdjacentTaskFragments() {
+ final Task task = createTask(mDisplayContent);
+ mTaskFragment = new TaskFragmentBuilder(mAtm)
+ .setParentTask(task)
+ .setFragmentToken(mFragmentToken)
+ .build();
+ mWindowOrganizerController.mLaunchTaskFragments.put(mFragmentToken, mTaskFragment);
+ final IBinder fragmentToken2 = new Binder();
+ final TaskFragment taskFragment2 = new TaskFragmentBuilder(mAtm)
+ .setParentTask(task)
+ .setFragmentToken(fragmentToken2)
+ .build();
+ mWindowOrganizerController.mLaunchTaskFragments.put(fragmentToken2, taskFragment2);
+ mTaskFragment.setAdjacentTaskFragment(taskFragment2);
+
+ mTransaction.clearAdjacentTaskFragments(mFragmentToken);
+ mOrganizer.applyTransaction(mTransaction, TASK_FRAGMENT_TRANSIT_CHANGE,
+ false /* shouldApplyIndependently */);
+
+ // Not allowed because TaskFragment is not organized by the caller organizer.
+ assertApplyTransactionDisallowed(mTransaction);
+ assertEquals(taskFragment2, mTaskFragment.getAdjacentTaskFragment());
+
+ mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* uid */,
+ "Test:TaskFragmentOrganizer" /* processName */);
+
+ assertApplyTransactionAllowed(mTransaction);
+ assertNull(mTaskFragment.getAdjacentTaskFragment());
+ assertNull(taskFragment2.getAdjacentTaskFragment());
}
@Test
@@ -779,6 +819,38 @@
}
@Test
+ public void testApplyTransaction_createTaskFragment_overrideBounds() {
+ final Task task = createTask(mDisplayContent);
+ final ActivityRecord activityAtBottom = createActivityRecord(task);
+ final int uid = Binder.getCallingUid();
+ activityAtBottom.info.applicationInfo.uid = uid;
+ activityAtBottom.getTask().effectiveUid = uid;
+ mTaskFragment = new TaskFragmentBuilder(mAtm)
+ .setParentTask(task)
+ .setFragmentToken(mFragmentToken)
+ .createActivityCount(1)
+ .build();
+ mWindowOrganizerController.mLaunchTaskFragments.put(mFragmentToken, mTaskFragment);
+ final IBinder fragmentToken1 = new Binder();
+ final Rect bounds = new Rect(100, 100, 500, 1000);
+ final TaskFragmentCreationParams params = new TaskFragmentCreationParams.Builder(
+ mOrganizerToken, fragmentToken1, activityAtBottom.token)
+ .setPairedActivityToken(activityAtBottom.token)
+ .setInitialBounds(bounds)
+ .build();
+ mTransaction.setTaskFragmentOrganizer(mIOrganizer);
+ mTransaction.createTaskFragment(params);
+ assertApplyTransactionAllowed(mTransaction);
+
+ // Successfully created a TaskFragment.
+ final TaskFragment taskFragment = mWindowOrganizerController.getTaskFragment(
+ fragmentToken1);
+ assertNotNull(taskFragment);
+ // The relative embedded bounds is updated to the initial requested bounds.
+ assertEquals(bounds, taskFragment.getRelativeEmbeddedBounds());
+ }
+
+ @Test
public void testApplyTransaction_createTaskFragment_withPairedActivityToken() {
final Task task = createTask(mDisplayContent);
final ActivityRecord activityAtBottom = createActivityRecord(task);
@@ -1016,8 +1088,7 @@
spyOn(mWindowOrganizerController);
// Not allow to set adjacent on a TaskFragment that is in a PIP Task.
- mTransaction.setAdjacentTaskFragments(mFragmentToken, null /* fragmentToken2 */,
- null /* options */)
+ mTransaction.setAdjacentTaskFragments(mFragmentToken, new Binder(), null /* options */)
.setErrorCallbackToken(mErrorToken);
assertApplyTransactionAllowed(mTransaction);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 6bce959..1f60e79 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -552,7 +552,12 @@
win.applyWithNextDraw(t -> handledT[0] = t);
assertTrue(win.useBLASTSync());
final SurfaceControl.Transaction drawT = new StubTransaction();
+ final SurfaceControl.Transaction currT = win.getSyncTransaction();
+ clearInvocations(currT);
+ win.mWinAnimator.mLastHidden = true;
assertTrue(win.finishDrawing(drawT, Integer.MAX_VALUE));
+ // The draw transaction should be merged to current transaction even if the state is hidden.
+ verify(currT).merge(eq(drawT));
assertEquals(drawT, handledT[0]);
assertFalse(win.useBLASTSync());
diff --git a/services/usb/java/com/android/server/usb/UsbAlsaManager.java b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
index 42a5af7..17c354a 100644
--- a/services/usb/java/com/android/server/usb/UsbAlsaManager.java
+++ b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
@@ -36,6 +36,7 @@
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashMap;
import java.util.List;
/**
@@ -106,6 +107,12 @@
return false;
}
+ /**
+ * List of connected MIDI devices
+ */
+ private final HashMap<String, UsbMidiDevice>
+ mMidiDevices = new HashMap<String, UsbMidiDevice>();
+
// UsbMidiDevice for USB peripheral mode (gadget) device
private UsbMidiDevice mPeripheralMidiDevice = null;
@@ -249,6 +256,8 @@
}
}
+ addMidiDevice(deviceAddress, usbDevice, parser, cardRec);
+
logDevices("deviceAdded()");
if (DEBUG) {
@@ -256,6 +265,54 @@
}
}
+ private void addMidiDevice(String deviceAddress, UsbDevice usbDevice,
+ UsbDescriptorParser parser, AlsaCardsParser.AlsaCardRecord cardRec) {
+ boolean hasMidi = parser.hasMIDIInterface();
+ // UsbHostManager will create UsbDirectMidiDevices instead if MIDI 2 is supported.
+ boolean hasMidi2 = parser.containsUniversalMidiDeviceEndpoint();
+ if (DEBUG) {
+ Slog.d(TAG, "hasMidi: " + hasMidi + " mHasMidiFeature:" + mHasMidiFeature);
+ Slog.d(TAG, "hasMidi2: " + hasMidi2);
+ }
+ if (mHasMidiFeature && hasMidi && !hasMidi2) {
+ Bundle properties = new Bundle();
+ String manufacturer = usbDevice.getManufacturerName();
+ String product = usbDevice.getProductName();
+ String version = usbDevice.getVersion();
+ String name;
+ if (manufacturer == null || manufacturer.isEmpty()) {
+ name = product;
+ } else if (product == null || product.isEmpty()) {
+ name = manufacturer;
+ } else {
+ name = manufacturer + " " + product;
+ }
+ properties.putString(MidiDeviceInfo.PROPERTY_NAME, name);
+ properties.putString(MidiDeviceInfo.PROPERTY_MANUFACTURER, manufacturer);
+ properties.putString(MidiDeviceInfo.PROPERTY_PRODUCT, product);
+ properties.putString(MidiDeviceInfo.PROPERTY_VERSION, version);
+ properties.putString(MidiDeviceInfo.PROPERTY_SERIAL_NUMBER,
+ usbDevice.getSerialNumber());
+ properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_CARD, cardRec.getCardNum());
+ properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_DEVICE, 0 /*deviceNum*/);
+ properties.putParcelable(MidiDeviceInfo.PROPERTY_USB_DEVICE, usbDevice);
+
+ int numLegacyMidiInputs = parser.calculateNumLegacyMidiInputs();
+ int numLegacyMidiOutputs = parser.calculateNumLegacyMidiOutputs();
+ if (DEBUG) {
+ Slog.d(TAG, "numLegacyMidiInputs: " + numLegacyMidiInputs);
+ Slog.d(TAG, "numLegacyMidiOutputs:" + numLegacyMidiOutputs);
+ }
+
+ UsbMidiDevice usbMidiDevice = UsbMidiDevice.create(mContext, properties,
+ cardRec.getCardNum(), 0 /*device*/, numLegacyMidiInputs,
+ numLegacyMidiOutputs);
+ if (usbMidiDevice != null) {
+ mMidiDevices.put(deviceAddress, usbMidiDevice);
+ }
+ }
+ }
+
/* package */ synchronized void usbDeviceRemoved(String deviceAddress/*UsbDevice usbDevice*/) {
if (DEBUG) {
Slog.d(TAG, "deviceRemoved(" + deviceAddress + ")");
@@ -269,6 +326,13 @@
selectDefaultDevice(); // if there any external devices left, select one of them
}
+ // MIDI
+ UsbMidiDevice usbMidiDevice = mMidiDevices.remove(deviceAddress);
+ if (usbMidiDevice != null) {
+ Slog.i(TAG, "USB MIDI Device Removed: " + deviceAddress);
+ IoUtils.closeQuietly(usbMidiDevice);
+ }
+
logDevices("usbDeviceRemoved()");
}
@@ -324,6 +388,12 @@
usbAlsaDevice.dump(dump, "alsa_devices", UsbAlsaManagerProto.ALSA_DEVICES);
}
+ for (String deviceAddr : mMidiDevices.keySet()) {
+ // A UsbMidiDevice does not have a handle to the UsbDevice anymore
+ mMidiDevices.get(deviceAddr).dump(deviceAddr, dump, "midi_devices",
+ UsbAlsaManagerProto.MIDI_DEVICES);
+ }
+
dump.end(token);
}
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index b6aed2db..a480ebd 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -536,7 +536,6 @@
private boolean mInHostModeWithNoAccessoryConnected;
private boolean mSourcePower;
private boolean mSinkPower;
- private boolean mConfigured;
private boolean mAudioAccessoryConnected;
private boolean mAudioAccessorySupported;
private boolean mConnectedToDataDisabledPort;
@@ -571,7 +570,12 @@
private final UsbPermissionManager mPermissionManager;
private NotificationManager mNotificationManager;
+ /**
+ * Do not debounce for the first disconnect after resetUsbGadget.
+ */
+ protected boolean mResetUsbGadgetDisableDebounce;
protected boolean mConnected;
+ protected boolean mConfigured;
protected long mScreenUnlockedFunctions;
protected boolean mBootCompleted;
protected boolean mCurrentFunctionsApplied;
@@ -716,15 +720,29 @@
Slog.e(TAG, "unknown state " + state);
return;
}
- if (configured == 0) removeMessages(MSG_UPDATE_STATE);
if (connected == 1) removeMessages(MSG_FUNCTION_SWITCH_TIMEOUT);
Message msg = Message.obtain(this, MSG_UPDATE_STATE);
msg.arg1 = connected;
msg.arg2 = configured;
- // debounce disconnects to avoid problems bringing up USB tethering
- sendMessageDelayed(msg,
+ if (DEBUG) {
+ Slog.i(TAG, "mResetUsbGadgetDisableDebounce:" + mResetUsbGadgetDisableDebounce
+ + " connected:" + connected + "configured:" + configured);
+ }
+ if (mResetUsbGadgetDisableDebounce) {
+ // Do not debounce disconnect after resetUsbGadget.
+ sendMessage(msg);
+ if (connected == 1) mResetUsbGadgetDisableDebounce = false;
+ } else {
+ if (configured == 0) {
+ removeMessages(MSG_UPDATE_STATE);
+ if (DEBUG) Slog.i(TAG, "removeMessages MSG_UPDATE_STATE");
+ }
+ if (connected == 1) removeMessages(MSG_FUNCTION_SWITCH_TIMEOUT);
+ // debounce disconnects to avoid problems bringing up USB tethering.
+ sendMessageDelayed(msg,
(connected == 0) ? (mScreenLocked ? DEVICE_STATE_UPDATE_DELAY
: DEVICE_STATE_UPDATE_DELAY_EXT) : 0);
+ }
}
public void updateHostState(UsbPort port, UsbPortStatus status) {
@@ -974,7 +992,10 @@
int operationId = sUsbOperationCount.incrementAndGet();
mConnected = (msg.arg1 == 1);
mConfigured = (msg.arg2 == 1);
-
+ if (DEBUG) {
+ Slog.i(TAG, "handleMessage MSG_UPDATE_STATE " + "mConnected:" + mConnected
+ + " mConfigured:" + mConfigured);
+ }
updateUsbNotification(false);
updateAdbNotification(false);
if (mBootCompleted) {
@@ -2132,9 +2153,16 @@
}
try {
+ // MSG_ACCESSORY_MODE_ENTER_TIMEOUT has to be removed to allow exiting
+ // AOAP mode during resetUsbGadget.
+ removeMessages(MSG_ACCESSORY_MODE_ENTER_TIMEOUT);
+ if (mConfigured) {
+ mResetUsbGadgetDisableDebounce = true;
+ }
mUsbGadgetHal.reset();
} catch (Exception e) {
Slog.e(TAG, "reset Usb Gadget failed", e);
+ mResetUsbGadgetDisableDebounce = false;
}
}
break;
diff --git a/services/usb/java/com/android/server/usb/UsbHostManager.java b/services/usb/java/com/android/server/usb/UsbHostManager.java
index f389276..b3eb285 100644
--- a/services/usb/java/com/android/server/usb/UsbHostManager.java
+++ b/services/usb/java/com/android/server/usb/UsbHostManager.java
@@ -444,14 +444,19 @@
} else {
Slog.e(TAG, "Universal Midi Device is null.");
}
- }
- if (parser.containsLegacyMidiDeviceEndpoint()) {
- UsbDirectMidiDevice midiDevice = UsbDirectMidiDevice.create(mContext,
- newDevice, parser, false, uniqueUsbDeviceIdentifier);
- if (midiDevice != null) {
- midiDevices.add(midiDevice);
- } else {
- Slog.e(TAG, "Legacy Midi Device is null.");
+
+ // Use UsbDirectMidiDevice only if this supports MIDI 2.0 as well.
+ // ALSA removes the audio sound card if MIDI interfaces are removed.
+ // This means that as long as ALSA is used for audio, MIDI 1.0 USB
+ // devices should use the ALSA path for MIDI.
+ if (parser.containsLegacyMidiDeviceEndpoint()) {
+ midiDevice = UsbDirectMidiDevice.create(mContext,
+ newDevice, parser, false, uniqueUsbDeviceIdentifier);
+ if (midiDevice != null) {
+ midiDevices.add(midiDevice);
+ } else {
+ Slog.e(TAG, "Legacy Midi Device is null.");
+ }
}
}
diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbConfigDescriptor.java b/services/usb/java/com/android/server/usb/descriptors/UsbConfigDescriptor.java
index 3f2d8c8..c6ea228 100644
--- a/services/usb/java/com/android/server/usb/descriptors/UsbConfigDescriptor.java
+++ b/services/usb/java/com/android/server/usb/descriptors/UsbConfigDescriptor.java
@@ -79,6 +79,10 @@
mInterfaceDescriptors.add(interfaceDesc);
}
+ ArrayList<UsbInterfaceDescriptor> getInterfaceDescriptors() {
+ return mInterfaceDescriptors;
+ }
+
private boolean isAudioInterface(UsbInterfaceDescriptor descriptor) {
return descriptor.getUsbClass() == UsbDescriptor.CLASSID_AUDIO
&& descriptor.getUsbSubclass() == UsbDescriptor.AUDIO_AUDIOSTREAMING;
diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java b/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java
index f13fcd8..10b7952 100644
--- a/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java
+++ b/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java
@@ -40,6 +40,7 @@
private UsbDeviceDescriptor mDeviceDescriptor;
private UsbConfigDescriptor mCurConfigDescriptor;
private UsbInterfaceDescriptor mCurInterfaceDescriptor;
+ private UsbEndpointDescriptor mCurEndpointDescriptor;
// The AudioClass spec implemented by the AudioClass Interfaces
// This may well be different than the overall USB Spec.
@@ -165,7 +166,7 @@
break;
case UsbDescriptor.DESCRIPTORTYPE_ENDPOINT:
- descriptor = new UsbEndpointDescriptor(length, type);
+ descriptor = mCurEndpointDescriptor = new UsbEndpointDescriptor(length, type);
if (mCurInterfaceDescriptor != null) {
mCurInterfaceDescriptor.addEndpointDescriptor(
(UsbEndpointDescriptor) descriptor);
@@ -265,6 +266,9 @@
+ Integer.toHexString(subClass));
break;
}
+ if (mCurEndpointDescriptor != null && descriptor != null) {
+ mCurEndpointDescriptor.setClassSpecificEndpointDescriptor(descriptor);
+ }
}
break;
@@ -798,6 +802,84 @@
/**
* @hide
*/
+ private int calculateNumLegacyMidiPorts(boolean isOutput) {
+ // Only look at the first config.
+ UsbConfigDescriptor configDescriptor = null;
+ for (UsbDescriptor descriptor : mDescriptors) {
+ if (descriptor.getType() == UsbDescriptor.DESCRIPTORTYPE_CONFIG) {
+ if (descriptor instanceof UsbConfigDescriptor) {
+ configDescriptor = (UsbConfigDescriptor) descriptor;
+ break;
+ } else {
+ Log.w(TAG, "Unrecognized Config l: " + descriptor.getLength()
+ + " t:0x" + Integer.toHexString(descriptor.getType()));
+ }
+ }
+ }
+ if (configDescriptor == null) {
+ Log.w(TAG, "Config not found");
+ return 0;
+ }
+
+ ArrayList<UsbInterfaceDescriptor> legacyMidiInterfaceDescriptors =
+ new ArrayList<UsbInterfaceDescriptor>();
+ for (UsbInterfaceDescriptor interfaceDescriptor
+ : configDescriptor.getInterfaceDescriptors()) {
+ if (interfaceDescriptor.getUsbClass() == UsbDescriptor.CLASSID_AUDIO) {
+ if (interfaceDescriptor.getUsbSubclass() == UsbDescriptor.AUDIO_MIDISTREAMING) {
+ UsbDescriptor midiHeaderDescriptor =
+ interfaceDescriptor.getMidiHeaderInterfaceDescriptor();
+ if (midiHeaderDescriptor != null) {
+ if (midiHeaderDescriptor instanceof UsbMSMidiHeader) {
+ UsbMSMidiHeader midiHeader =
+ (UsbMSMidiHeader) midiHeaderDescriptor;
+ if (midiHeader.getMidiStreamingClass() == MS_MIDI_1_0) {
+ legacyMidiInterfaceDescriptors.add(interfaceDescriptor);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ int count = 0;
+ for (UsbInterfaceDescriptor interfaceDescriptor : legacyMidiInterfaceDescriptors) {
+ for (int i = 0; i < interfaceDescriptor.getNumEndpoints(); i++) {
+ UsbEndpointDescriptor endpoint =
+ interfaceDescriptor.getEndpointDescriptor(i);
+ // 0 is output, 1 << 7 is input.
+ if ((endpoint.getDirection() == 0) == isOutput) {
+ UsbDescriptor classSpecificEndpointDescriptor =
+ endpoint.getClassSpecificEndpointDescriptor();
+ if (classSpecificEndpointDescriptor != null
+ && (classSpecificEndpointDescriptor instanceof UsbACMidi10Endpoint)) {
+ UsbACMidi10Endpoint midiEndpoint =
+ (UsbACMidi10Endpoint) classSpecificEndpointDescriptor;
+ count += midiEndpoint.getNumJacks();
+ }
+ }
+ }
+ }
+ return count;
+ }
+
+ /**
+ * @hide
+ */
+ public int calculateNumLegacyMidiInputs() {
+ return calculateNumLegacyMidiPorts(false /*isOutput*/);
+ }
+
+ /**
+ * @hide
+ */
+ public int calculateNumLegacyMidiOutputs() {
+ return calculateNumLegacyMidiPorts(true /*isOutput*/);
+ }
+
+ /**
+ * @hide
+ */
public float getInputHeadsetProbability() {
if (hasMIDIInterface()) {
return 0.0f;
diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbEndpointDescriptor.java b/services/usb/java/com/android/server/usb/descriptors/UsbEndpointDescriptor.java
index ab07ce7..1f448ac 100644
--- a/services/usb/java/com/android/server/usb/descriptors/UsbEndpointDescriptor.java
+++ b/services/usb/java/com/android/server/usb/descriptors/UsbEndpointDescriptor.java
@@ -79,6 +79,8 @@
private byte mRefresh;
private byte mSyncAddress;
+ private UsbDescriptor mClassSpecificEndpointDescriptor;
+
public UsbEndpointDescriptor(int length, byte type) {
super(length, type);
mHierarchyLevel = 4;
@@ -112,6 +114,14 @@
return mEndpointAddress & UsbEndpointDescriptor.MASK_ENDPOINT_DIRECTION;
}
+ void setClassSpecificEndpointDescriptor(UsbDescriptor descriptor) {
+ mClassSpecificEndpointDescriptor = descriptor;
+ }
+
+ UsbDescriptor getClassSpecificEndpointDescriptor() {
+ return mClassSpecificEndpointDescriptor;
+ }
+
/**
* Returns a UsbEndpoint that this UsbEndpointDescriptor is describing.
*/
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/DetectorSession.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/DetectorSession.java
index 4d6d320..b8536f9 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/DetectorSession.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/DetectorSession.java
@@ -205,9 +205,15 @@
mVoiceInteractionServiceUid = voiceInteractionServiceUid;
mVoiceInteractorIdentity = voiceInteractorIdentity;
mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
- mHotwordAudioStreamCopier = new HotwordAudioStreamCopier(mAppOpsManager, getDetectorType(),
- mVoiceInteractorIdentity.uid, mVoiceInteractorIdentity.packageName,
- mVoiceInteractorIdentity.attributionTag);
+ if (getDetectorType() != HotwordDetector.DETECTOR_TYPE_VISUAL_QUERY_DETECTOR) {
+ mHotwordAudioStreamCopier = new HotwordAudioStreamCopier(mAppOpsManager,
+ getDetectorType(),
+ mVoiceInteractorIdentity.uid, mVoiceInteractorIdentity.packageName,
+ mVoiceInteractorIdentity.attributionTag);
+ } else {
+ mHotwordAudioStreamCopier = null;
+ }
+
mScheduledExecutorService = scheduledExecutorService;
mDebugHotwordLogging = logging;
@@ -236,9 +242,12 @@
future.complete(null);
if (mUpdateStateAfterStartFinished.getAndSet(true)) {
Slog.w(TAG, "call callback after timeout");
- HotwordMetricsLogger.writeDetectorEvent(getDetectorType(),
+ if (getDetectorType()
+ != HotwordDetector.DETECTOR_TYPE_VISUAL_QUERY_DETECTOR) {
+ HotwordMetricsLogger.writeDetectorEvent(getDetectorType(),
HOTWORD_DETECTOR_EVENTS__EVENT__CALLBACK_UPDATE_STATE_AFTER_TIMEOUT,
mVoiceInteractionServiceUid);
+ }
return;
}
Pair<Integer, Integer> statusResultPair = getInitStatusAndMetricsResult(bundle);
@@ -246,27 +255,37 @@
int initResultMetricsResult = statusResultPair.second;
try {
mCallback.onStatusReported(status);
- HotwordMetricsLogger.writeServiceInitResultEvent(getDetectorType(),
- initResultMetricsResult, mVoiceInteractionServiceUid);
+ if (getDetectorType()
+ != HotwordDetector.DETECTOR_TYPE_VISUAL_QUERY_DETECTOR) {
+ HotwordMetricsLogger.writeServiceInitResultEvent(getDetectorType(),
+ initResultMetricsResult, mVoiceInteractionServiceUid);
+ }
} catch (RemoteException e) {
Slog.w(TAG, "Failed to report initialization status: " + e);
- HotwordMetricsLogger.writeDetectorEvent(getDetectorType(),
- METRICS_CALLBACK_ON_STATUS_REPORTED_EXCEPTION,
- mVoiceInteractionServiceUid);
+ if (getDetectorType()
+ != HotwordDetector.DETECTOR_TYPE_VISUAL_QUERY_DETECTOR) {
+ HotwordMetricsLogger.writeDetectorEvent(getDetectorType(),
+ METRICS_CALLBACK_ON_STATUS_REPORTED_EXCEPTION,
+ mVoiceInteractionServiceUid);
+ }
}
}
};
try {
service.updateState(options, sharedMemory, statusCallback);
- HotwordMetricsLogger.writeDetectorEvent(getDetectorType(),
- HOTWORD_DETECTOR_EVENTS__EVENT__REQUEST_UPDATE_STATE,
- mVoiceInteractionServiceUid);
+ if (getDetectorType() != HotwordDetector.DETECTOR_TYPE_VISUAL_QUERY_DETECTOR) {
+ HotwordMetricsLogger.writeDetectorEvent(getDetectorType(),
+ HOTWORD_DETECTOR_EVENTS__EVENT__REQUEST_UPDATE_STATE,
+ mVoiceInteractionServiceUid);
+ }
} catch (RemoteException e) {
// TODO: (b/181842909) Report an error to voice interactor
Slog.w(TAG, "Failed to updateState for HotwordDetectionService", e);
- HotwordMetricsLogger.writeDetectorEvent(getDetectorType(),
- HOTWORD_DETECTOR_EVENTS__EVENT__CALL_UPDATE_STATE_EXCEPTION,
- mVoiceInteractionServiceUid);
+ if (getDetectorType() != HotwordDetector.DETECTOR_TYPE_VISUAL_QUERY_DETECTOR) {
+ HotwordMetricsLogger.writeDetectorEvent(getDetectorType(),
+ HOTWORD_DETECTOR_EVENTS__EVENT__CALL_UPDATE_STATE_EXCEPTION,
+ mVoiceInteractionServiceUid);
+ }
}
return future.orTimeout(MAX_UPDATE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
}).whenComplete((res, err) -> {
@@ -277,13 +296,17 @@
}
try {
mCallback.onStatusReported(INITIALIZATION_STATUS_UNKNOWN);
- HotwordMetricsLogger.writeServiceInitResultEvent(getDetectorType(),
- METRICS_INIT_UNKNOWN_TIMEOUT, mVoiceInteractionServiceUid);
+ if (getDetectorType() != HotwordDetector.DETECTOR_TYPE_VISUAL_QUERY_DETECTOR) {
+ HotwordMetricsLogger.writeServiceInitResultEvent(getDetectorType(),
+ METRICS_INIT_UNKNOWN_TIMEOUT, mVoiceInteractionServiceUid);
+ }
} catch (RemoteException e) {
Slog.w(TAG, "Failed to report initialization status UNKNOWN", e);
- HotwordMetricsLogger.writeDetectorEvent(getDetectorType(),
- METRICS_CALLBACK_ON_STATUS_REPORTED_EXCEPTION,
- mVoiceInteractionServiceUid);
+ if (getDetectorType() != HotwordDetector.DETECTOR_TYPE_VISUAL_QUERY_DETECTOR) {
+ HotwordMetricsLogger.writeDetectorEvent(getDetectorType(),
+ METRICS_CALLBACK_ON_STATUS_REPORTED_EXCEPTION,
+ mVoiceInteractionServiceUid);
+ }
}
} else if (err != null) {
Slog.w(TAG, "Failed to update state: " + err);
@@ -315,9 +338,11 @@
@SuppressWarnings("GuardedBy")
void updateStateLocked(PersistableBundle options, SharedMemory sharedMemory,
Instant lastRestartInstant) {
- HotwordMetricsLogger.writeDetectorEvent(getDetectorType(),
- HOTWORD_DETECTOR_EVENTS__EVENT__APP_REQUEST_UPDATE_STATE,
- mVoiceInteractionServiceUid);
+ if (getDetectorType() != HotwordDetector.DETECTOR_TYPE_VISUAL_QUERY_DETECTOR) {
+ HotwordMetricsLogger.writeDetectorEvent(getDetectorType(),
+ HOTWORD_DETECTOR_EVENTS__EVENT__APP_REQUEST_UPDATE_STATE,
+ mVoiceInteractionServiceUid);
+ }
// Prevent doing the init late, so restart is handled equally to a clean process start.
// TODO(b/191742511): this logic needs a test
if (!mUpdateStateAfterStartFinished.get() && Instant.now().minus(
@@ -399,9 +424,11 @@
callback.onError();
} catch (RemoteException ex) {
Slog.w(TAG, "Failed to report onError status: " + ex);
- HotwordMetricsLogger.writeDetectorEvent(getDetectorType(),
- HOTWORD_DETECTOR_EVENTS__EVENT__CALLBACK_ON_ERROR_EXCEPTION,
- mVoiceInteractionServiceUid);
+ if (getDetectorType() != HotwordDetector.DETECTOR_TYPE_VISUAL_QUERY_DETECTOR) {
+ HotwordMetricsLogger.writeDetectorEvent(getDetectorType(),
+ HOTWORD_DETECTOR_EVENTS__EVENT__CALLBACK_ON_ERROR_EXCEPTION,
+ mVoiceInteractionServiceUid);
+ }
}
} finally {
synchronized (mLock) {
@@ -427,7 +454,8 @@
throws RemoteException {
synchronized (mLock) {
mPerformingExternalSourceHotwordDetection = false;
- HotwordMetricsLogger.writeDetectorEvent(getDetectorType(),
+ HotwordMetricsLogger.writeDetectorEvent(
+ getDetectorType(),
METRICS_EXTERNAL_SOURCE_REJECTED,
mVoiceInteractionServiceUid);
mScheduledExecutorService.schedule(
@@ -454,7 +482,8 @@
throws RemoteException {
synchronized (mLock) {
mPerformingExternalSourceHotwordDetection = false;
- HotwordMetricsLogger.writeDetectorEvent(getDetectorType(),
+ HotwordMetricsLogger.writeDetectorEvent(
+ getDetectorType(),
METRICS_EXTERNAL_SOURCE_DETECTED,
mVoiceInteractionServiceUid);
mScheduledExecutorService.schedule(
@@ -540,9 +569,11 @@
mCallback.onError(status);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to report onError status: " + e);
- HotwordMetricsLogger.writeDetectorEvent(getDetectorType(),
- HOTWORD_DETECTOR_EVENTS__EVENT__CALLBACK_ON_ERROR_EXCEPTION,
- mVoiceInteractionServiceUid);
+ if (getDetectorType() != HotwordDetector.DETECTOR_TYPE_VISUAL_QUERY_DETECTOR) {
+ HotwordMetricsLogger.writeDetectorEvent(getDetectorType(),
+ HOTWORD_DETECTOR_EVENTS__EVENT__CALLBACK_ON_ERROR_EXCEPTION,
+ mVoiceInteractionServiceUid);
+ }
}
}
@@ -679,6 +710,8 @@
return HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_DSP;
} else if (this instanceof SoftwareTrustedHotwordDetectorSession) {
return HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE;
+ } else if (this instanceof VisualQueryDetectorSession) {
+ return HotwordDetector.DETECTOR_TYPE_VISUAL_QUERY_DETECTOR;
}
Slog.v(TAG, "Unexpected detector type");
return -1;
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
index d501af7..665d5e7 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
@@ -52,6 +52,8 @@
import android.service.voice.HotwordDetector;
import android.service.voice.IMicrophoneHotwordDetectionVoiceInteractionCallback;
import android.service.voice.ISandboxedDetectionService;
+import android.service.voice.IVisualQueryDetectionVoiceInteractionCallback;
+import android.service.voice.VisualQueryDetectionService;
import android.service.voice.VoiceInteractionManagerInternal.HotwordDetectionServiceIdentity;
import android.speech.IRecognitionServiceManager;
import android.util.Slog;
@@ -74,7 +76,8 @@
import java.util.function.Function;
/**
- * A class that provides the communication with the HotwordDetectionService.
+ * A class that provides the communication with the {@link HotwordDetectionService} and
+ * {@link VisualQueryDetectionService}.
*/
final class HotwordDetectionConnection {
private static final String TAG = "HotwordDetectionConnection";
@@ -90,7 +93,8 @@
@Nullable private final ScheduledFuture<?> mCancellationTaskFuture;
private final IBinder.DeathRecipient mAudioServerDeathRecipient = this::audioServerDied;
@NonNull private final ServiceConnectionFactory mHotwordDetectionServiceConnectionFactory;
- private final int mDetectorType;
+ @NonNull private final ServiceConnectionFactory mVisualQueryDetectionServiceConnectionFactory;
+ private int mDetectorType;
/**
* Time after which each HotwordDetectionService process is stopped and replaced by a new one.
* 0 indicates no restarts.
@@ -100,9 +104,11 @@
final Object mLock;
final int mVoiceInteractionServiceUid;
final ComponentName mHotwordDetectionComponentName;
+ final ComponentName mVisualQueryDetectionComponentName;
final int mUser;
final Context mContext;
volatile HotwordDetectionServiceIdentity mIdentity;
+ //TODO: add similar identity for visual query service for the use of content capturing
private Instant mLastRestartInstant;
private ScheduledFuture<?> mDebugHotwordLoggingTimeoutFuture = null;
@@ -112,6 +118,7 @@
@Nullable
private final Identity mVoiceInteractorIdentity;
@NonNull private ServiceConnection mRemoteHotwordDetectionService;
+ @NonNull private ServiceConnection mRemoteVisualQueryDetectionService;
private IBinder mAudioFlinger;
@GuardedBy("mLock")
private boolean mDebugHotwordLogging = false;
@@ -126,26 +133,39 @@
new SparseArray<>();
HotwordDetectionConnection(Object lock, Context context, int voiceInteractionServiceUid,
- Identity voiceInteractorIdentity, ComponentName hotwordDetectionServiceName, int userId,
+ Identity voiceInteractorIdentity, ComponentName hotwordDetectionServiceName,
+ ComponentName visualQueryDetectionServiceName, int userId,
boolean bindInstantServiceAllowed, int detectorType) {
mLock = lock;
mContext = context;
mVoiceInteractionServiceUid = voiceInteractionServiceUid;
mVoiceInteractorIdentity = voiceInteractorIdentity;
mHotwordDetectionComponentName = hotwordDetectionServiceName;
+ mVisualQueryDetectionComponentName = visualQueryDetectionServiceName;
mUser = userId;
mDetectorType = detectorType;
mReStartPeriodSeconds = DeviceConfig.getInt(DeviceConfig.NAMESPACE_VOICE_INTERACTION,
KEY_RESTART_PERIOD_IN_SECONDS, 0);
+
final Intent hotwordDetectionServiceIntent =
new Intent(HotwordDetectionService.SERVICE_INTERFACE);
hotwordDetectionServiceIntent.setComponent(mHotwordDetectionComponentName);
+
+ final Intent visualQueryDetectionServiceIntent =
+ new Intent(VisualQueryDetectionService.SERVICE_INTERFACE);
+ visualQueryDetectionServiceIntent.setComponent(mVisualQueryDetectionComponentName);
+
initAudioFlingerLocked();
mHotwordDetectionServiceConnectionFactory =
new ServiceConnectionFactory(hotwordDetectionServiceIntent,
bindInstantServiceAllowed);
- mRemoteHotwordDetectionService = mHotwordDetectionServiceConnectionFactory.createLocked();
+
+ mVisualQueryDetectionServiceConnectionFactory =
+ new ServiceConnectionFactory(visualQueryDetectionServiceIntent,
+ bindInstantServiceAllowed);
+
+
mLastRestartInstant = Instant.now();
if (mReStartPeriodSeconds <= 0) {
@@ -157,9 +177,11 @@
Slog.v(TAG, "Time to restart the process, TTL has passed");
synchronized (mLock) {
restartProcessLocked();
- HotwordMetricsLogger.writeServiceRestartEvent(mDetectorType,
- HOTWORD_DETECTION_SERVICE_RESTARTED__REASON__SCHEDULE,
- mVoiceInteractionServiceUid);
+ if (mDetectorType != HotwordDetector.DETECTOR_TYPE_VISUAL_QUERY_DETECTOR) {
+ HotwordMetricsLogger.writeServiceRestartEvent(mDetectorType,
+ HOTWORD_DETECTION_SERVICE_RESTARTED__REASON__SCHEDULE,
+ mVoiceInteractionServiceUid);
+ }
}
}, mReStartPeriodSeconds, mReStartPeriodSeconds, TimeUnit.SECONDS);
}
@@ -193,9 +215,11 @@
// We restart the process instead of simply sending over the new binder, to avoid race
// conditions with audio reading in the service.
restartProcessLocked();
- HotwordMetricsLogger.writeServiceRestartEvent(mDetectorType,
- HOTWORD_DETECTION_SERVICE_RESTARTED__REASON__AUDIO_SERVICE_DIED,
- mVoiceInteractionServiceUid);
+ if (mDetectorType != HotwordDetector.DETECTOR_TYPE_VISUAL_QUERY_DETECTOR) {
+ HotwordMetricsLogger.writeServiceRestartEvent(mDetectorType,
+ HOTWORD_DETECTION_SERVICE_RESTARTED__REASON__AUDIO_SERVICE_DIED,
+ mVoiceInteractionServiceUid);
+ }
}
}
@@ -208,9 +232,8 @@
});
mDetectorSessions.clear();
mDebugHotwordLogging = false;
- mRemoteHotwordDetectionService.unbind();
- LocalServices.getService(PermissionManagerServiceInternal.class)
- .setHotwordDetectionServiceProvider(null);
+ unbindVisualQueryDetectionService();
+ unbindHotwordDetectionService();
if (mIdentity != null) {
removeServiceUidForAudioPolicy(mIdentity.getIsolatedUid());
}
@@ -223,6 +246,21 @@
}
}
+ private void unbindVisualQueryDetectionService() {
+ if (mRemoteVisualQueryDetectionService != null) {
+ mRemoteVisualQueryDetectionService.unbind();
+ //TODO: Set visual query detection service provider to null
+ }
+ }
+
+ private void unbindHotwordDetectionService() {
+ if (mRemoteHotwordDetectionService != null) {
+ mRemoteHotwordDetectionService.unbind();
+ LocalServices.getService(PermissionManagerServiceInternal.class)
+ .setHotwordDetectionServiceProvider(null);
+ }
+ }
+
@SuppressWarnings("GuardedBy")
void updateStateLocked(PersistableBundle options, SharedMemory sharedMemory,
@NonNull IBinder token) {
@@ -253,6 +291,34 @@
session.startListeningFromMicLocked(audioFormat, callback);
}
+ /**
+ * This method is only used by VisualQueryDetector.
+ */
+ void startPerceivingLocked(IVisualQueryDetectionVoiceInteractionCallback callback) {
+ if (DEBUG) {
+ Slog.d(TAG, "startPerceivingLocked");
+ }
+ final VisualQueryDetectorSession session = getVisualQueryDetectorSessionLocked();
+ if (session == null) {
+ return;
+ }
+ session.startPerceivingLocked(callback);
+ }
+
+ /**
+ * This method is only used by VisaulQueryDetector.
+ */
+ void stopPerceivingLocked() {
+ if (DEBUG) {
+ Slog.d(TAG, "stopPerceivingLocked");
+ }
+ final VisualQueryDetectorSession session = getVisualQueryDetectorSessionLocked();
+ if (session == null) {
+ return;
+ }
+ session.stopPerceivingLocked();
+ }
+
public void startListeningFromExternalSourceLocked(
ParcelFileDescriptor audioStream,
AudioFormat audioFormat,
@@ -342,6 +408,10 @@
}
}
+ void setDetectorType(int detectorType) {
+ mDetectorType = detectorType;
+ }
+
private void clearDebugHotwordLoggingTimeoutLocked() {
if (mDebugHotwordLoggingTimeoutFuture != null) {
mDebugHotwordLoggingTimeoutFuture.cancel(/* mayInterruptIfRunning= */ true);
@@ -353,24 +423,41 @@
private void restartProcessLocked() {
// TODO(b/244598068): Check HotwordAudioStreamManager first
Slog.v(TAG, "Restarting hotword detection process");
+
ServiceConnection oldHotwordConnection = mRemoteHotwordDetectionService;
+ ServiceConnection oldVisualQueryDetectionConnection = mRemoteVisualQueryDetectionService;
HotwordDetectionServiceIdentity previousIdentity = mIdentity;
+ //TODO: Add previousIdentity for visual query detection service
mLastRestartInstant = Instant.now();
// Recreate connection to reset the cache.
+
mRemoteHotwordDetectionService = mHotwordDetectionServiceConnectionFactory.createLocked();
+ mRemoteVisualQueryDetectionService =
+ mVisualQueryDetectionServiceConnectionFactory.createLocked();
Slog.v(TAG, "Started the new process, dispatching processRestarted to detector");
runForEachDetectorSessionLocked((session) -> {
- session.updateRemoteSandboxedDetectionServiceLocked(mRemoteHotwordDetectionService);
+ HotwordDetectionConnection.ServiceConnection newRemoteService =
+ (session instanceof VisualQueryDetectorSession)
+ ? mRemoteVisualQueryDetectionService : mRemoteHotwordDetectionService;
+ session.updateRemoteSandboxedDetectionServiceLocked(newRemoteService);
session.informRestartProcessLocked();
});
if (DEBUG) {
Slog.i(TAG, "processRestarted is dispatched done, unbinding from the old process");
}
- oldHotwordConnection.ignoreConnectionStatusEvents();
- oldHotwordConnection.unbind();
+ if (oldHotwordConnection != null) {
+ oldHotwordConnection.ignoreConnectionStatusEvents();
+ oldHotwordConnection.unbind();
+ }
+
+ if (oldVisualQueryDetectionConnection != null) {
+ oldVisualQueryDetectionConnection.ignoreConnectionStatusEvents();
+ oldVisualQueryDetectionConnection.unbind();
+ }
+
if (previousIdentity != null) {
removeServiceUidForAudioPolicy(previousIdentity.getIsolatedUid());
}
@@ -438,9 +525,14 @@
synchronized (mLock) {
pw.print(prefix); pw.print("mReStartPeriodSeconds="); pw.println(mReStartPeriodSeconds);
pw.print(prefix); pw.print("mBound=");
- pw.println(mRemoteHotwordDetectionService.isBound());
+ pw.println(mRemoteHotwordDetectionService != null
+ && mRemoteHotwordDetectionService.isBound());
+ pw.println(mRemoteVisualQueryDetectionService != null
+ && mRemoteHotwordDetectionService != null
+ && mRemoteHotwordDetectionService.isBound());
pw.print(prefix); pw.print("mRestartCount=");
pw.println(mHotwordDetectionServiceConnectionFactory.mRestartCount);
+ pw.println(mVisualQueryDetectionServiceConnectionFactory.mRestartCount);
pw.print(prefix); pw.print("mLastRestartInstant="); pw.println(mLastRestartInstant);
pw.print(prefix); pw.print("mDetectorType=");
pw.println(HotwordDetector.detectorTypeToString(mDetectorType));
@@ -489,11 +581,11 @@
private boolean mIsLoggedFirstConnect = false;
ServiceConnection(@NonNull Context context,
- @NonNull Intent intent, int bindingFlags, int userId,
+ @NonNull Intent serviceIntent, int bindingFlags, int userId,
@Nullable Function<IBinder, ISandboxedDetectionService> binderAsInterface,
int instanceNumber) {
- super(context, intent, bindingFlags, userId, binderAsInterface);
- this.mIntent = intent;
+ super(context, serviceIntent, bindingFlags, userId, binderAsInterface);
+ this.mIntent = serviceIntent;
this.mBindingFlags = bindingFlags;
this.mInstanceNumber = instanceNumber;
}
@@ -512,14 +604,18 @@
mIsBound = connected;
if (!connected) {
- HotwordMetricsLogger.writeDetectorEvent(mDetectorType,
- HOTWORD_DETECTOR_EVENTS__EVENT__ON_DISCONNECTED,
- mVoiceInteractionServiceUid);
+ if (mDetectorType != HotwordDetector.DETECTOR_TYPE_VISUAL_QUERY_DETECTOR) {
+ HotwordMetricsLogger.writeDetectorEvent(mDetectorType,
+ HOTWORD_DETECTOR_EVENTS__EVENT__ON_DISCONNECTED,
+ mVoiceInteractionServiceUid);
+ }
} else if (!mIsLoggedFirstConnect) {
mIsLoggedFirstConnect = true;
- HotwordMetricsLogger.writeDetectorEvent(mDetectorType,
- HOTWORD_DETECTOR_EVENTS__EVENT__ON_CONNECTED,
- mVoiceInteractionServiceUid);
+ if (mDetectorType != HotwordDetector.DETECTOR_TYPE_VISUAL_QUERY_DETECTOR) {
+ HotwordMetricsLogger.writeDetectorEvent(mDetectorType,
+ HOTWORD_DETECTOR_EVENTS__EVENT__ON_CONNECTED,
+ mVoiceInteractionServiceUid);
+ }
}
}
}
@@ -539,6 +635,7 @@
return;
}
}
+ //TODO(b265535257): report error to either service only.
synchronized (HotwordDetectionConnection.this.mLock) {
runForEachDetectorSessionLocked((session) -> {
session.reportErrorLocked(
@@ -546,35 +643,46 @@
});
}
// Can improve to log exit reason if needed
- HotwordMetricsLogger.writeKeyphraseTriggerEvent(
- mDetectorType,
- HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__SERVICE_CRASH,
- mVoiceInteractionServiceUid);
+ if (mDetectorType != HotwordDetector.DETECTOR_TYPE_VISUAL_QUERY_DETECTOR) {
+ HotwordMetricsLogger.writeKeyphraseTriggerEvent(
+ mDetectorType,
+ HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__SERVICE_CRASH,
+ mVoiceInteractionServiceUid);
+ }
}
@Override
protected boolean bindService(
@NonNull android.content.ServiceConnection serviceConnection) {
try {
- HotwordMetricsLogger.writeDetectorEvent(mDetectorType,
- HOTWORD_DETECTOR_EVENTS__EVENT__REQUEST_BIND_SERVICE,
- mVoiceInteractionServiceUid);
+ if (mDetectorType != HotwordDetector.DETECTOR_TYPE_VISUAL_QUERY_DETECTOR) {
+ HotwordMetricsLogger.writeDetectorEvent(mDetectorType,
+ HOTWORD_DETECTOR_EVENTS__EVENT__REQUEST_BIND_SERVICE,
+ mVoiceInteractionServiceUid);
+ }
+ String instancePrefix =
+ mIntent.getAction().equals(HotwordDetectionService.SERVICE_INTERFACE)
+ ? "hotword_detector_" : "visual_query_detector_";
boolean bindResult = mContext.bindIsolatedService(
mIntent,
Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE | mBindingFlags,
- "hotword_detector_" + mInstanceNumber,
+ instancePrefix + mInstanceNumber,
mExecutor,
serviceConnection);
if (!bindResult) {
+ if (mDetectorType != HotwordDetector.DETECTOR_TYPE_VISUAL_QUERY_DETECTOR) {
+ HotwordMetricsLogger.writeDetectorEvent(mDetectorType,
+ HOTWORD_DETECTOR_EVENTS__EVENT__REQUEST_BIND_SERVICE_FAIL,
+ mVoiceInteractionServiceUid);
+ }
+ }
+ return bindResult;
+ } catch (IllegalArgumentException e) {
+ if (mDetectorType != HotwordDetector.DETECTOR_TYPE_VISUAL_QUERY_DETECTOR) {
HotwordMetricsLogger.writeDetectorEvent(mDetectorType,
HOTWORD_DETECTOR_EVENTS__EVENT__REQUEST_BIND_SERVICE_FAIL,
mVoiceInteractionServiceUid);
}
- return bindResult;
- } catch (IllegalArgumentException e) {
- HotwordMetricsLogger.writeDetectorEvent(mDetectorType,
- HOTWORD_DETECTOR_EVENTS__EVENT__REQUEST_BIND_SERVICE_FAIL,
- mVoiceInteractionServiceUid);
Slog.wtf(TAG, "Can't bind to the hotword detection service!", e);
return false;
}
@@ -609,10 +717,27 @@
}
final DetectorSession session;
if (detectorType == HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_DSP) {
+ if (mRemoteHotwordDetectionService == null) {
+ mRemoteHotwordDetectionService =
+ mHotwordDetectionServiceConnectionFactory.createLocked();
+ }
session = new DspTrustedHotwordDetectorSession(mRemoteHotwordDetectionService,
mLock, mContext, token, callback, mVoiceInteractionServiceUid,
mVoiceInteractorIdentity, mScheduledExecutorService, mDebugHotwordLogging);
+ } else if (detectorType == HotwordDetector.DETECTOR_TYPE_VISUAL_QUERY_DETECTOR) {
+ if (mRemoteVisualQueryDetectionService == null) {
+ mRemoteVisualQueryDetectionService =
+ mVisualQueryDetectionServiceConnectionFactory.createLocked();
+ }
+ session = new VisualQueryDetectorSession(
+ mRemoteVisualQueryDetectionService, mLock, mContext, token, callback,
+ mVoiceInteractionServiceUid, mVoiceInteractorIdentity,
+ mScheduledExecutorService, mDebugHotwordLogging);
} else {
+ if (mRemoteHotwordDetectionService == null) {
+ mRemoteHotwordDetectionService =
+ mHotwordDetectionServiceConnectionFactory.createLocked();
+ }
session = new SoftwareTrustedHotwordDetectorSession(
mRemoteHotwordDetectionService, mLock, mContext, token, callback,
mVoiceInteractionServiceUid, mVoiceInteractorIdentity,
@@ -625,13 +750,23 @@
@SuppressWarnings("GuardedBy")
void destroyDetectorLocked(@NonNull IBinder token) {
final DetectorSession session = getDetectorSessionByTokenLocked(token);
- if (session != null) {
- session.destroyLocked();
- final int index = mDetectorSessions.indexOfValue(session);
- if (index < 0 || index > mDetectorSessions.size() - 1) {
- return;
- }
- mDetectorSessions.removeAt(index);
+ if (session == null) {
+ return;
+ }
+ session.destroyLocked();
+ final int index = mDetectorSessions.indexOfValue(session);
+ if (index < 0 || index > mDetectorSessions.size() - 1) {
+ return;
+ }
+ mDetectorSessions.removeAt(index);
+ if (session instanceof VisualQueryDetectorSession) {
+ unbindVisualQueryDetectionService();
+ }
+ // Handle case where all hotword detector sessions are destroyed with only the visual
+ // detector session left
+ if (mDetectorSessions.size() == 1
+ && mDetectorSessions.get(0) instanceof VisualQueryDetectorSession) {
+ unbindHotwordDetectionService();
}
}
@@ -672,6 +807,15 @@
}
@SuppressWarnings("GuardedBy")
+ private VisualQueryDetectorSession getVisualQueryDetectorSessionLocked() {
+ final DetectorSession session = mDetectorSessions.get(
+ HotwordDetector.DETECTOR_TYPE_VISUAL_QUERY_DETECTOR);
+ if (session == null || session.isDestroyed()) {
+ Slog.v(TAG, "Not found the look and talk perceiver");
+ return null;
+ }
+ return (VisualQueryDetectorSession) session;
+ }
private void runForEachDetectorSessionLocked(
@NonNull Consumer<DetectorSession> action) {
for (int i = 0; i < mDetectorSessions.size(); i++) {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VisualQueryDetectorSession.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VisualQueryDetectorSession.java
new file mode 100644
index 0000000..621c3de
--- /dev/null
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VisualQueryDetectorSession.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.voiceinteraction;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.media.AudioFormat;
+import android.media.permission.Identity;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+import android.os.PersistableBundle;
+import android.os.RemoteException;
+import android.os.SharedMemory;
+import android.service.voice.IDetectorSessionVisualQueryDetectionCallback;
+import android.service.voice.IMicrophoneHotwordDetectionVoiceInteractionCallback;
+import android.service.voice.ISandboxedDetectionService;
+import android.service.voice.IVisualQueryDetectionVoiceInteractionCallback;
+import android.util.Slog;
+
+import com.android.internal.app.IHotwordRecognitionStatusCallback;
+
+import java.io.PrintWriter;
+import java.util.Objects;
+import java.util.concurrent.ScheduledExecutorService;
+
+/**
+ * A class that provides visual query detector to communicate with the {@link
+ * android.service.voice.VisualQueryDetectionService}.
+ *
+ * This class can handle the visual query detection whose detector is created by using
+ * {@link android.service.voice.VoiceInteractionService#createVisualQueryDetector(PersistableBundle
+ * ,SharedMemory, HotwordDetector.Callback)}.
+ */
+final class VisualQueryDetectorSession extends DetectorSession {
+
+ private static final String TAG = "VisualQueryDetectorSession";
+ private boolean mEgressingData;
+ private boolean mQueryStreaming;
+
+ //TODO(b/261783819): Determines actual functionalities, e.g., startRecognition etc.
+ VisualQueryDetectorSession(
+ @NonNull HotwordDetectionConnection.ServiceConnection remoteService,
+ @NonNull Object lock, @NonNull Context context, @NonNull IBinder token,
+ @NonNull IHotwordRecognitionStatusCallback callback, int voiceInteractionServiceUid,
+ Identity voiceInteractorIdentity,
+ @NonNull ScheduledExecutorService scheduledExecutorService, boolean logging) {
+ super(remoteService, lock, context, token, callback,
+ voiceInteractionServiceUid, voiceInteractorIdentity, scheduledExecutorService,
+ logging);
+ mEgressingData = false;
+ mQueryStreaming = false;
+ }
+
+ @Override
+ @SuppressWarnings("GuardedBy")
+ void informRestartProcessLocked() {
+ Slog.v(TAG, "informRestartProcessLocked");
+ mUpdateStateAfterStartFinished.set(false);
+ //TODO(b/261783819): Starts detection in VisualQueryDetectionService.
+ }
+
+ @SuppressWarnings("GuardedBy")
+ void startPerceivingLocked(IVisualQueryDetectionVoiceInteractionCallback callback) {
+ if (DEBUG) {
+ Slog.d(TAG, "startPerceivingLocked");
+ }
+
+ IDetectorSessionVisualQueryDetectionCallback internalCallback =
+ new IDetectorSessionVisualQueryDetectionCallback.Stub(){
+
+ @Override
+ public void onAttentionGained() {
+ Slog.v(TAG, "BinderCallback#onAttentionGained");
+ //TODO check to see if there is an active SysUI listener registered
+ mEgressingData = true;
+ }
+
+ @Override
+ public void onAttentionLost() {
+ Slog.v(TAG, "BinderCallback#onAttentionLost");
+ //TODO check to see if there is an active SysUI listener registered
+ mEgressingData = false;
+ }
+
+ @Override
+ public void onQueryDetected(@NonNull String partialQuery) throws RemoteException {
+ Objects.requireNonNull(partialQuery);
+ Slog.v(TAG, "BinderCallback#onQueryDetected");
+ if (!mEgressingData) {
+ Slog.v(TAG, "Query should not be egressed within the unattention state.");
+ return;
+ }
+ mQueryStreaming = true;
+ callback.onQueryDetected(partialQuery);
+ Slog.i(TAG, "Egressed from visual query detection process.");
+ }
+
+ @Override
+ public void onQueryFinished() throws RemoteException {
+ Slog.v(TAG, "BinderCallback#onQueryFinished");
+ if (!mQueryStreaming) {
+ Slog.v(TAG, "Query streaming state signal FINISHED is block since there is"
+ + " no active query being streamed.");
+ return;
+ }
+ callback.onQueryFinished();
+ mQueryStreaming = false;
+ }
+
+ @Override
+ public void onQueryRejected() throws RemoteException {
+ Slog.v(TAG, "BinderCallback#onQueryRejected");
+ if (!mQueryStreaming) {
+ Slog.v(TAG, "Query streaming state signal REJECTED is block since there is"
+ + " no active query being streamed.");
+ return;
+ }
+ callback.onQueryRejected();
+ mQueryStreaming = false;
+ }
+ };
+ mRemoteDetectionService.run(service -> service.detectWithVisualSignals(internalCallback));
+ }
+
+ @SuppressWarnings("GuardedBy")
+ void stopPerceivingLocked() {
+ if (DEBUG) {
+ Slog.d(TAG, "stopPerceivingLocked");
+ }
+ mRemoteDetectionService.run(ISandboxedDetectionService::stopDetection);
+ }
+
+ @Override
+ void startListeningFromExternalSourceLocked(
+ ParcelFileDescriptor audioStream,
+ AudioFormat audioFormat,
+ @Nullable PersistableBundle options,
+ IMicrophoneHotwordDetectionVoiceInteractionCallback callback)
+ throws UnsupportedOperationException {
+ throw new UnsupportedOperationException("HotwordDetectionService method"
+ + " should not be called from VisualQueryDetectorSession.");
+ }
+
+
+ @SuppressWarnings("GuardedBy")
+ public void dumpLocked(String prefix, PrintWriter pw) {
+ super.dumpLocked(prefix, pw);
+ pw.print(prefix);
+ }
+}
+
+
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 9a02188..38bf9c2 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -72,6 +72,7 @@
import android.os.UserHandle;
import android.provider.Settings;
import android.service.voice.IMicrophoneHotwordDetectionVoiceInteractionCallback;
+import android.service.voice.IVisualQueryDetectionVoiceInteractionCallback;
import android.service.voice.IVoiceInteractionSession;
import android.service.voice.VoiceInteractionManagerInternal;
import android.service.voice.VoiceInteractionService;
@@ -330,6 +331,12 @@
@GuardedBy("this")
private boolean mTemporarilyDisabled;
+ /** The start value of showSessionId */
+ private static final int SHOW_SESSION_START_ID = 0;
+
+ @GuardedBy("this")
+ private int mShowSessionId = SHOW_SESSION_START_ID;
+
private final boolean mEnableService;
// TODO(b/226201975): remove reference once RoleService supports pre-created users
private final RoleObserver mRoleObserver;
@@ -349,6 +356,24 @@
}
}
+ int getNextShowSessionId() {
+ synchronized (this) {
+ // Reset the showSessionId to SHOW_SESSION_START_ID to avoid the value exceeds
+ // Integer.MAX_VALUE
+ if (mShowSessionId == Integer.MAX_VALUE - 1) {
+ mShowSessionId = SHOW_SESSION_START_ID;
+ }
+ mShowSessionId++;
+ return mShowSessionId;
+ }
+ }
+
+ int getShowSessionId() {
+ synchronized (this) {
+ return mShowSessionId;
+ }
+ }
+
@Override
public @NonNull IVoiceInteractionSoundTriggerSession createSoundTriggerSessionAsOriginator(
@NonNull Identity originatorIdentity, IBinder client) {
@@ -1314,6 +1339,46 @@
}
@Override
+ public void startPerceiving(
+ IVisualQueryDetectionVoiceInteractionCallback callback)
+ throws RemoteException {
+ enforceCallingPermission(Manifest.permission.RECORD_AUDIO);
+ enforceCallingPermission(Manifest.permission.CAMERA);
+ synchronized (this) {
+ enforceIsCurrentVoiceInteractionService();
+
+ if (mImpl == null) {
+ Slog.w(TAG, "startPerceiving without running voice interaction service");
+ return;
+ }
+ final long caller = Binder.clearCallingIdentity();
+ try {
+ mImpl.startPerceivingLocked(callback);
+ } finally {
+ Binder.restoreCallingIdentity(caller);
+ }
+ }
+ }
+
+ @Override
+ public void stopPerceiving() throws RemoteException {
+ synchronized (this) {
+ enforceIsCurrentVoiceInteractionService();
+
+ if (mImpl == null) {
+ Slog.w(TAG, "stopPerceiving without running voice interaction service");
+ return;
+ }
+ final long caller = Binder.clearCallingIdentity();
+ try {
+ mImpl.stopPerceivingLocked();
+ } finally {
+ Binder.restoreCallingIdentity(caller);
+ }
+ }
+ }
+
+ @Override
public void startListeningFromMic(
AudioFormat audioFormat,
IMicrophoneHotwordDetectionVoiceInteractionCallback callback)
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index 9643282..04c8f8f 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -21,6 +21,7 @@
import static android.app.ActivityManager.START_VOICE_HIDDEN_SESSION;
import static android.app.ActivityManager.START_VOICE_NOT_ACTIVE_SESSION;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
+import static android.service.voice.VoiceInteractionService.KEY_SHOW_SESSION_ID;
import static com.android.server.policy.PhoneWindowManager.SYSTEM_DIALOG_REASON_ASSIST;
@@ -58,7 +59,9 @@
import android.os.ServiceManager;
import android.os.SharedMemory;
import android.os.UserHandle;
+import android.service.voice.HotwordDetector;
import android.service.voice.IMicrophoneHotwordDetectionVoiceInteractionCallback;
+import android.service.voice.IVisualQueryDetectionVoiceInteractionCallback;
import android.service.voice.IVoiceInteractionService;
import android.service.voice.IVoiceInteractionSession;
import android.service.voice.VoiceInteractionService;
@@ -109,6 +112,7 @@
final ComponentName mSessionComponentName;
final IWindowManager mIWindowManager;
final ComponentName mHotwordDetectionComponentName;
+ final ComponentName mVisualQueryDetectionComponentName;
boolean mBound = false;
IVoiceInteractionService mService;
volatile HotwordDetectionConnection mHotwordDetectionConnection;
@@ -211,6 +215,7 @@
mInfo = null;
mSessionComponentName = null;
mHotwordDetectionComponentName = null;
+ mVisualQueryDetectionComponentName = null;
mIWindowManager = null;
mValid = false;
return;
@@ -220,6 +225,7 @@
Slog.w(TAG, "Bad voice interaction service: " + mInfo.getParseError());
mSessionComponentName = null;
mHotwordDetectionComponentName = null;
+ mVisualQueryDetectionComponentName = null;
mIWindowManager = null;
mValid = false;
return;
@@ -230,6 +236,9 @@
final String hotwordDetectionServiceName = mInfo.getHotwordDetectionService();
mHotwordDetectionComponentName = hotwordDetectionServiceName != null
? new ComponentName(service.getPackageName(), hotwordDetectionServiceName) : null;
+ final String visualQueryDetectionServiceName = mInfo.getVisualQueryDetectionService();
+ mVisualQueryDetectionComponentName = visualQueryDetectionServiceName != null ? new
+ ComponentName(service.getPackageName(), visualQueryDetectionServiceName) : null;
mIWindowManager = IWindowManager.Stub.asInterface(
ServiceManager.getService(Context.WINDOW_SERVICE));
IntentFilter filter = new IntentFilter();
@@ -247,15 +256,39 @@
/* direct= */ true);
}
- public boolean showSessionLocked(@NonNull Bundle args, int flags,
+ public boolean showSessionLocked(@Nullable Bundle args, int flags,
@Nullable String attributionTag,
@Nullable IVoiceInteractionSessionShowCallback showCallback,
@Nullable IBinder activityToken) {
+ final int sessionId = mServiceStub.getNextShowSessionId();
+ final Bundle newArgs = args == null ? new Bundle() : args;
+ newArgs.putInt(KEY_SHOW_SESSION_ID, sessionId);
+
+ try {
+ if (mService != null) {
+ mService.prepareToShowSession(newArgs, flags);
+ }
+ } catch (RemoteException e) {
+ Slog.w(TAG, "RemoteException while calling prepareToShowSession", e);
+ }
+
if (mActiveSession == null) {
mActiveSession = new VoiceInteractionSessionConnection(mServiceStub,
mSessionComponentName, mUser, mContext, this,
mInfo.getServiceInfo().applicationInfo.uid, mHandler);
}
+ if (!mActiveSession.mBound) {
+ try {
+ if (mService != null) {
+ Bundle failedArgs = new Bundle();
+ failedArgs.putInt(KEY_SHOW_SESSION_ID, sessionId);
+ mService.showSessionFailed(failedArgs);
+ }
+ } catch (RemoteException e) {
+ Slog.w(TAG, "RemoteException while calling showSessionFailed", e);
+ }
+ }
+
List<ActivityAssistInfo> allVisibleActivities =
LocalServices.getService(ActivityTaskManagerInternal.class)
.getTopVisibleActivities();
@@ -274,7 +307,7 @@
} else {
visibleActivities = allVisibleActivities;
}
- return mActiveSession.showLocked(args, flags, attributionTag, mDisabledShowContext,
+ return mActiveSession.showLocked(newArgs, flags, attributionTag, mDisabledShowContext,
showCallback, visibleActivities);
}
@@ -573,14 +606,11 @@
}
}
- public void initAndVerifyDetectorLocked(
- @NonNull Identity voiceInteractorIdentity,
- @Nullable PersistableBundle options,
+ private void verifyDetectorForHotwordDetectionLocked(
@Nullable SharedMemory sharedMemory,
- @NonNull IBinder token,
IHotwordRecognitionStatusCallback callback,
int detectorType) {
- Slog.v(TAG, "initAndVerifyDetectorLocked");
+ Slog.v(TAG, "verifyDetectorForHotwordDetectionLocked");
int voiceInteractionServiceUid = mInfo.getServiceInfo().applicationInfo.uid;
if (mHotwordDetectionComponentName == null) {
Slog.w(TAG, "Hotword detection service name not found");
@@ -631,11 +661,70 @@
logDetectorCreateEventIfNeeded(callback, detectorType, true,
voiceInteractionServiceUid);
+ }
+
+ private void verifyDetectorForVisualQueryDetectionLocked(@Nullable SharedMemory sharedMemory) {
+ Slog.v(TAG, "verifyDetectorForVisualQueryDetectionLocked");
+
+ if (mVisualQueryDetectionComponentName == null) {
+ Slog.w(TAG, "Visual query detection service name not found");
+ throw new IllegalStateException("Visual query detection service name not found");
+ }
+ ServiceInfo visualQueryDetectionServiceInfo = getServiceInfoLocked(
+ mVisualQueryDetectionComponentName, mUser);
+ if (visualQueryDetectionServiceInfo == null) {
+ Slog.w(TAG, "Visual query detection service info not found");
+ throw new IllegalStateException("Visual query detection service name not found");
+ }
+ if (!isIsolatedProcessLocked(visualQueryDetectionServiceInfo)) {
+ Slog.w(TAG, "Visual query detection service not in isolated process");
+ throw new IllegalStateException("Visual query detection not in isolated process");
+ }
+ if (!Manifest.permission.BIND_VISUAL_QUERY_DETECTION_SERVICE.equals(
+ visualQueryDetectionServiceInfo.permission)) {
+ Slog.w(TAG, "Visual query detection does not require permission "
+ + Manifest.permission.BIND_VISUAL_QUERY_DETECTION_SERVICE);
+ throw new SecurityException("Visual query detection does not require permission "
+ + Manifest.permission.BIND_VISUAL_QUERY_DETECTION_SERVICE);
+ }
+ if (mContext.getPackageManager().checkPermission(
+ Manifest.permission.BIND_VISUAL_QUERY_DETECTION_SERVICE,
+ mInfo.getServiceInfo().packageName) == PackageManager.PERMISSION_GRANTED) {
+ Slog.w(TAG, "Voice interaction service should not hold permission "
+ + Manifest.permission.BIND_VISUAL_QUERY_DETECTION_SERVICE);
+ throw new SecurityException("Voice interaction service should not hold permission "
+ + Manifest.permission.BIND_VISUAL_QUERY_DETECTION_SERVICE);
+ }
+ if (sharedMemory != null && !sharedMemory.setProtect(OsConstants.PROT_READ)) {
+ Slog.w(TAG, "Can't set sharedMemory to be read-only");
+ throw new IllegalStateException("Can't set sharedMemory to be read-only");
+ }
+ }
+
+ public void initAndVerifyDetectorLocked(
+ @NonNull Identity voiceInteractorIdentity,
+ @Nullable PersistableBundle options,
+ @Nullable SharedMemory sharedMemory,
+ @NonNull IBinder token,
+ IHotwordRecognitionStatusCallback callback,
+ int detectorType) {
+
+ if (detectorType != HotwordDetector.DETECTOR_TYPE_VISUAL_QUERY_DETECTOR) {
+ verifyDetectorForHotwordDetectionLocked(sharedMemory, callback, detectorType);
+ } else {
+ verifyDetectorForVisualQueryDetectionLocked(sharedMemory);
+ }
+
if (mHotwordDetectionConnection == null) {
mHotwordDetectionConnection = new HotwordDetectionConnection(mServiceStub, mContext,
mInfo.getServiceInfo().applicationInfo.uid, voiceInteractorIdentity,
- mHotwordDetectionComponentName, mUser, /* bindInstantServiceAllowed= */ false,
- detectorType);
+ mHotwordDetectionComponentName, mVisualQueryDetectionComponentName, mUser,
+ /* bindInstantServiceAllowed= */ false, detectorType);
+ } else if (detectorType != HotwordDetector.DETECTOR_TYPE_VISUAL_QUERY_DETECTOR) {
+ // TODO: Logger events should be handled in session instead. Temporary adding the
+ // checking to prevent confusion so VisualQueryDetection events won't be logged if the
+ // connection is instantiated by the VisualQueryDetector.
+ mHotwordDetectionConnection.setDetectorType(detectorType);
}
mHotwordDetectionConnection.createDetectorLocked(options, sharedMemory, token, callback,
detectorType);
@@ -671,6 +760,32 @@
mHotwordDetectionConnection = null;
}
+ public void startPerceivingLocked(IVisualQueryDetectionVoiceInteractionCallback callback) {
+ if (DEBUG) {
+ Slog.d(TAG, "startPerceivingLocked");
+ }
+
+ if (mHotwordDetectionConnection == null) {
+ // TODO: callback.onError();
+ return;
+ }
+
+ mHotwordDetectionConnection.startPerceivingLocked(callback);
+ }
+
+ public void stopPerceivingLocked() {
+ if (DEBUG) {
+ Slog.d(TAG, "stopPerceivingLocked");
+ }
+
+ if (mHotwordDetectionConnection == null) {
+ Slog.w(TAG, "stopPerceivingLocked() called but connection isn't established");
+ return;
+ }
+
+ mHotwordDetectionConnection.stopPerceivingLocked();
+ }
+
public void startListeningFromMicLocked(
AudioFormat audioFormat,
IMicrophoneHotwordDetectionVoiceInteractionCallback callback) {
diff --git a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
index f90eabc..d4a8600 100644
--- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
@@ -108,6 +108,21 @@
}
}
+ /**
+ * Check whether the caller (or self, if not processing an IPC) has internet permission.
+ * @param context app context
+ * @param message detail message
+ * @return true if permission is granted, else false
+ */
+ public static boolean checkInternetPermissionNoThrow(Context context, String message) {
+ try {
+ context.enforcePermission(Manifest.permission.INTERNET,
+ Binder.getCallingPid(), Binder.getCallingUid(), message);
+ return true;
+ } catch (SecurityException se) {
+ return false;
+ }
+ }
/**
* Check whether the caller (or self, if not processing an IPC) has non dangerous
diff --git a/telephony/java/android/service/euicc/EuiccService.java b/telephony/java/android/service/euicc/EuiccService.java
index e19117b..2c0087e 100644
--- a/telephony/java/android/service/euicc/EuiccService.java
+++ b/telephony/java/android/service/euicc/EuiccService.java
@@ -490,6 +490,28 @@
int slotId, DownloadableSubscription subscription, boolean forceDeactivateSim);
/**
+ * Populate {@link DownloadableSubscription} metadata for the given downloadable subscription.
+ *
+ * @param slotId ID of the SIM slot to use for the operation.
+ * @param portIndex Index of the port from the slot. portIndex is used if the eUICC must
+ * be activated to perform the operation.
+ * @param subscription A subscription whose metadata needs to be populated.
+ * @param forceDeactivateSim If true, and if an active SIM must be deactivated to access the
+ * eUICC, perform this action automatically. Otherwise, {@link #RESULT_MUST_DEACTIVATE_SIM}
+ * should be returned to allow the user to consent to this operation first.
+ * @return The result of the operation.
+ * @see android.telephony.euicc.EuiccManager#getDownloadableSubscriptionMetadata
+ */
+ @NonNull
+ public GetDownloadableSubscriptionMetadataResult onGetDownloadableSubscriptionMetadata(
+ int slotId, int portIndex, @NonNull DownloadableSubscription subscription,
+ boolean forceDeactivateSim) {
+ // stub implementation, LPA needs to implement this
+ throw new UnsupportedOperationException(
+ "LPA must override onGetDownloadableSubscriptionMetadata");
+ }
+
+ /**
* Return metadata for subscriptions which are available for download for this device.
*
* @param slotId ID of the SIM slot to use for the operation.
@@ -833,16 +855,31 @@
}
@Override
- public void getDownloadableSubscriptionMetadata(int slotId,
+ public void getDownloadableSubscriptionMetadata(int slotId, int portIndex,
DownloadableSubscription subscription,
- boolean forceDeactivateSim,
+ boolean switchAfterDownload, boolean forceDeactivateSim,
IGetDownloadableSubscriptionMetadataCallback callback) {
mExecutor.execute(new Runnable() {
@Override
public void run() {
- GetDownloadableSubscriptionMetadataResult result =
- EuiccService.this.onGetDownloadableSubscriptionMetadata(
+ GetDownloadableSubscriptionMetadataResult result;
+ if (switchAfterDownload) {
+ try {
+ result = EuiccService.this.onGetDownloadableSubscriptionMetadata(
+ slotId, portIndex, subscription, forceDeactivateSim);
+ } catch (UnsupportedOperationException | AbstractMethodError e) {
+ Log.w(TAG, "The new onGetDownloadableSubscriptionMetadata(int, int, "
+ + "DownloadableSubscription, boolean) is not implemented."
+ + " Fall back to the old one.", e);
+ result = EuiccService.this.onGetDownloadableSubscriptionMetadata(
slotId, subscription, forceDeactivateSim);
+ }
+ } else {
+ // When switchAfterDownload is false, this operation is port agnostic.
+ // Call API without portIndex.
+ result = EuiccService.this.onGetDownloadableSubscriptionMetadata(
+ slotId, subscription, forceDeactivateSim);
+ }
try {
callback.onComplete(result);
} catch (RemoteException e) {
diff --git a/telephony/java/android/service/euicc/IEuiccService.aidl b/telephony/java/android/service/euicc/IEuiccService.aidl
index 6b0397d..f8d5ae9 100644
--- a/telephony/java/android/service/euicc/IEuiccService.aidl
+++ b/telephony/java/android/service/euicc/IEuiccService.aidl
@@ -38,8 +38,10 @@
void downloadSubscription(int slotId, int portIndex, in DownloadableSubscription subscription,
boolean switchAfterDownload, boolean forceDeactivateSim, in Bundle resolvedBundle,
in IDownloadSubscriptionCallback callback);
- void getDownloadableSubscriptionMetadata(int slotId, in DownloadableSubscription subscription,
- boolean forceDeactivateSim, in IGetDownloadableSubscriptionMetadataCallback callback);
+ void getDownloadableSubscriptionMetadata(
+ int slotId, int portIndex, in DownloadableSubscription subscription,
+ boolean switchAfterDownload, boolean forceDeactivateSim,
+ in IGetDownloadableSubscriptionMetadataCallback callback);
void getEid(int slotId, in IGetEidCallback callback);
void getOtaStatus(int slotId, in IGetOtaStatusCallback callback);
void startOtaIfNecessary(int slotId, in IOtaStatusChangedCallback statusChangedCallback);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 6f462b1..92d1e5b 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1796,8 +1796,6 @@
* Instead, each sim carrier should have a single country code, apply per carrier based iso
* code as an override. The overridden value can be read from
* {@link TelephonyManager#getSimCountryIso()} and {@link SubscriptionInfo#getCountryIso()}
- *
- * @hide
*/
public static final String KEY_SIM_COUNTRY_ISO_OVERRIDE_STRING =
"sim_country_iso_override_string";
diff --git a/telephony/java/android/telephony/ModemActivityInfo.java b/telephony/java/android/telephony/ModemActivityInfo.java
index 2d0135a..64b3c0a 100644
--- a/telephony/java/android/telephony/ModemActivityInfo.java
+++ b/telephony/java/android/telephony/ModemActivityInfo.java
@@ -567,14 +567,14 @@
/** @hide */
@TestApi
public boolean isEmpty() {
- boolean isTxPowerEmpty = false;
- boolean isRxPowerEmpty = false;
+ boolean isTxPowerEmpty = true;
+ boolean isRxPowerEmpty = true;
for (int i = 0; i < getSpecificInfoLength(); i++) {
- if (mActivityStatsTechSpecificInfo[i].isTxPowerEmpty()) {
- isTxPowerEmpty = true;
+ if (!mActivityStatsTechSpecificInfo[i].isTxPowerEmpty()) {
+ isTxPowerEmpty = false;
}
- if (mActivityStatsTechSpecificInfo[i].isRxPowerEmpty()) {
- isRxPowerEmpty = true;
+ if (!mActivityStatsTechSpecificInfo[i].isRxPowerEmpty()) {
+ isRxPowerEmpty = false;
}
}
return isTxPowerEmpty
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index a2a110d..26b4bbc 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -46,6 +46,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.telephony.IIntegerConsumer;
+import com.android.internal.telephony.IPhoneSubInfo;
import com.android.internal.telephony.ISms;
import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.SmsRawData;
@@ -3508,4 +3509,41 @@
private static String formatCrossStackMessageId(long id) {
return "{x-message-id:" + id + "}";
}
+
+ /**
+ * Fetches the EF_PSISMSC value from the UICC that contains the Public Service Identity of
+ * the SM-SC (either a SIP URI or tel URI). The EF_PSISMSC of ISIM and USIM can be found in
+ * DF_TELECOM.
+ * The EF_PSISMSC value is used by the ME to submit SMS over IP as defined in 24.341 [55].
+ *
+ * @return Uri : Public Service Identity of SM-SC from the ISIM or USIM if the ISIM is not
+ * available.
+ * @throws SecurityException if the caller does not have the required permission/privileges.
+ * @throws IllegalStateException in case of telephony service is not available.
+ * @hide
+ */
+ @NonNull
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
+ public Uri getSmscIdentity() {
+ Uri smscUri = Uri.EMPTY;
+ try {
+ IPhoneSubInfo info = TelephonyManager.getSubscriberInfoService();
+ if (info == null) {
+ Rlog.e(TAG, "getSmscIdentity(): IPhoneSubInfo instance is NULL");
+ throw new IllegalStateException("Telephony service is not available");
+ }
+ /** Fetches the SIM EF_PSISMSC value based on subId and appType */
+ smscUri = info.getSmscIdentity(getSubscriptionId(), TelephonyManager.APPTYPE_ISIM);
+ if (Uri.EMPTY.equals(smscUri)) {
+ /** Fallback in case where ISIM is not available */
+ smscUri = info.getSmscIdentity(getSubscriptionId(), TelephonyManager.APPTYPE_USIM);
+ }
+ } catch (RemoteException ex) {
+ Rlog.e(TAG, "getSmscIdentity(): Exception : " + ex);
+ ex.rethrowAsRuntimeException();
+ }
+ return smscUri;
+ }
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 0ad5ba0..913ea9a 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -17294,8 +17294,6 @@
* If displaying the performance boost notification is throttled, it will be for the amount of
* time specified by {@link CarrierConfigManager
* #KEY_PREMIUM_CAPABILITY_NOTIFICATION_BACKOFF_HYSTERESIS_TIME_MILLIS_LONG}.
- * If a foreground application requests premium capabilities, the performance boost notification
- * will be displayed to the user regardless of the throttled status.
* We will show the performance boost notification to the user up to the daily and monthly
* maximum number of times specified by
* {@link CarrierConfigManager#KEY_PREMIUM_CAPABILITY_MAXIMUM_DAILY_NOTIFICATION_COUNT_INT} and
@@ -17319,14 +17317,11 @@
public static final int PURCHASE_PREMIUM_CAPABILITY_RESULT_ALREADY_IN_PROGRESS = 4;
/**
- * Purchase premium capability failed because a foreground application requested the same
- * capability. The notification for the current application will be dismissed and a new
- * notification will be displayed to the user for the foreground application.
- * Subsequent attempts will return
- * {@link #PURCHASE_PREMIUM_CAPABILITY_RESULT_ALREADY_IN_PROGRESS} until the foreground
- * application's request is completed.
+ * Purchase premium capability failed because the requesting application is not in the
+ * foreground. Subsequent attempts will return the same error until the requesting application
+ * moves to the foreground.
*/
- public static final int PURCHASE_PREMIUM_CAPABILITY_RESULT_OVERRIDDEN = 5;
+ public static final int PURCHASE_PREMIUM_CAPABILITY_RESULT_NOT_FOREGROUND = 5;
/**
* Purchase premium capability failed because the user canceled the operation.
@@ -17423,7 +17418,7 @@
PURCHASE_PREMIUM_CAPABILITY_RESULT_THROTTLED,
PURCHASE_PREMIUM_CAPABILITY_RESULT_ALREADY_PURCHASED,
PURCHASE_PREMIUM_CAPABILITY_RESULT_ALREADY_IN_PROGRESS,
- PURCHASE_PREMIUM_CAPABILITY_RESULT_OVERRIDDEN,
+ PURCHASE_PREMIUM_CAPABILITY_RESULT_NOT_FOREGROUND,
PURCHASE_PREMIUM_CAPABILITY_RESULT_USER_CANCELED,
PURCHASE_PREMIUM_CAPABILITY_RESULT_CARRIER_DISABLED,
PURCHASE_PREMIUM_CAPABILITY_RESULT_CARRIER_ERROR,
@@ -17453,8 +17448,8 @@
return "ALREADY_PURCHASED";
case PURCHASE_PREMIUM_CAPABILITY_RESULT_ALREADY_IN_PROGRESS:
return "ALREADY_IN_PROGRESS";
- case PURCHASE_PREMIUM_CAPABILITY_RESULT_OVERRIDDEN:
- return "OVERRIDDEN";
+ case PURCHASE_PREMIUM_CAPABILITY_RESULT_NOT_FOREGROUND:
+ return "NOT_FOREGROUND";
case PURCHASE_PREMIUM_CAPABILITY_RESULT_USER_CANCELED:
return "USER_CANCELED";
case PURCHASE_PREMIUM_CAPABILITY_RESULT_CARRIER_DISABLED:
@@ -17491,10 +17486,12 @@
* @param executor The callback executor for the response.
* @param callback The result of the purchase request.
* One of {@link PurchasePremiumCapabilityResult}.
- * @throws SecurityException if the caller does not hold permission READ_BASIC_PHONE_STATE.
+ * @throws SecurityException if the caller does not hold permissions
+ * READ_BASIC_PHONE_STATE or INTERNET.
* @see #isPremiumCapabilityAvailableForPurchase(int) to check whether the capability is valid.
*/
- @RequiresPermission(android.Manifest.permission.READ_BASIC_PHONE_STATE)
+ @RequiresPermission(allOf = {android.Manifest.permission.READ_BASIC_PHONE_STATE,
+ android.Manifest.permission.INTERNET})
public void purchasePremiumCapability(@PremiumCapability int capability,
@NonNull @CallbackExecutor Executor executor,
@NonNull @PurchasePremiumCapabilityResult Consumer<Integer> callback) {
@@ -17715,37 +17712,6 @@
}
/**
- * Fetches the EFPSISMSC value from the SIM that contains the Public Service Identity
- * of the SM-SC (either a SIP URI or tel URI), the value is common for both appType
- * {@link #APPTYPE_ISIM} and {@link #APPTYPE_SIM}.
- * The EFPSISMSC value is used by the ME to submit SMS over IP as defined in 24.341 [55].
- *
- * @param appType ICC Application type {@link #APPTYPE_ISIM} or {@link #APPTYPE_USIM}
- * @return SIP URI or tel URI of the Public Service Identity of the SM-SC
- * @throws SecurityException if the caller does not have the required permission/privileges
- * @hide
- */
- @NonNull
- @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
- public String getSmscIdentity(int appType) {
- try {
- IPhoneSubInfo info = getSubscriberInfoService();
- if (info == null) {
- Rlog.e(TAG, "getSmscIdentity(): IPhoneSubInfo instance is NULL");
- return null;
- }
- /** Fetches the SIM PSISMSC params based on subId and appType */
- return info.getSmscIdentity(getSubId(), appType);
- } catch (RemoteException ex) {
- Rlog.e(TAG, "getSmscIdentity(): RemoteException: " + ex.getMessage());
- } catch (NullPointerException ex) {
- Rlog.e(TAG, "getSmscIdentity(): NullPointerException: " + ex.getMessage());
- }
- return null;
- }
-
- /**
* Returns a constant indicating the state of sim for the slot index.
*
* @param slotIndex Logical SIM slot index.
diff --git a/telephony/java/android/telephony/ims/RcsUceAdapter.java b/telephony/java/android/telephony/ims/RcsUceAdapter.java
index b49181e..3bb9be0 100644
--- a/telephony/java/android/telephony/ims/RcsUceAdapter.java
+++ b/telephony/java/android/telephony/ims/RcsUceAdapter.java
@@ -447,12 +447,12 @@
/**
* A callback for the response to a UCE request. The method
* {@link CapabilitiesCallback#onCapabilitiesReceived} will be called zero or more times as the
- * capabilities are received for each requested contact.
+ * capabilities are fetched from multiple sources, both cached on the device and on the network.
* <p>
* This request will take a varying amount of time depending on if the contacts requested are
* cached or if it requires a network query. The timeout time of these requests can vary
* depending on the network, however in poor cases it could take up to a minute for a request
- * to timeout. In that time only a subset of capabilities may have been retrieved.
+ * to timeout. In that time, only a subset of capabilities may have been retrieved.
* <p>
* After {@link CapabilitiesCallback#onComplete} or {@link CapabilitiesCallback#onError} has
* been called, the reference to this callback will be discarded on the service side.
@@ -463,22 +463,29 @@
public interface CapabilitiesCallback {
/**
- * Notify this application that the pending capability request has returned successfully
- * for one or more of the requested contacts.
+ * The pending capability request has completed successfully for one or more of the
+ * requested contacts.
+ * This may be called one or more times before the request is fully completed, as
+ * capabilities may need to be fetched from multiple sources both on device and on the
+ * network. Once the capabilities of all the requested contacts have been received,
+ * {@link #onComplete()} will be called. If there was an error during the capability
+ * exchange process, {@link #onError(int, long)} will be called instead.
* @param contactCapabilities List of capabilities associated with each contact requested.
*/
void onCapabilitiesReceived(@NonNull List<RcsContactUceCapability> contactCapabilities);
/**
- * The pending request has completed successfully due to all requested contacts information
- * being delivered. The callback {@link #onCapabilitiesReceived(List)}
- * for each contacts is required to be called before {@link #onComplete} is called.
+ * Called when the pending request has completed successfully due to all requested contacts
+ * information being delivered. The callback {@link #onCapabilitiesReceived(List)} will be
+ * called one or more times and will contain the contacts in the request that the device has
+ * received capabilities for.
*
- * @deprecated Replaced by {@link #onComplete(SipDetails)}, deprecated for
- * SIP information.
+ * @see #onComplete(SipDetails) onComplete(SipDetails) provides more information related to
+ * the underlying SIP transaction used to perform the capabilities exchange. Either this
+ * method or the alternate method should be implemented to determine when the request has
+ * completed successfully.
*/
- @Deprecated
- void onComplete();
+ default void onComplete() {}
/**
* The pending request has resulted in an error and may need to be retried, depending on the
@@ -487,18 +494,26 @@
* @param retryIntervalMillis The time in milliseconds the requesting application should
* wait before retrying, if non-zero.
*
- * @deprecated Replaced by {@link #onError(int, long, SipDetails)}, deprecated for
- * SIP information.
+ * @see #onError(int, long, SipDetails) onError(int, long, SipDetails) provides more
+ * information related to the underlying SIP transaction that resulted in an error. Either
+ * this method or the alternative method should be implemented to determine when the
+ * request has completed with an error.
*/
- @Deprecated
- void onError(@ErrorCode int errorCode, long retryIntervalMillis);
+ default void onError(@ErrorCode int errorCode, long retryIntervalMillis) {}
/**
- * The pending request has completed successfully due to all requested contacts information
- * being delivered. The callback {@link #onCapabilitiesReceived(List)}
- * for each contacts is required to be called before {@link #onComplete} is called.
+ * Called when the pending request has completed successfully due to all requested contacts
+ * information being delivered. The callback {@link #onCapabilitiesReceived(List)} will be
+ * called one or more times and will contain the contacts in the request that the device has
+ * received capabilities for.
*
- * @param details The SIP information related to this request.
+ * This method contains more information about the underlying SIP transaction if it exists.
+ * If this information is not needed, {@link #onComplete()} can be implemented
+ * instead.
+ *
+ * @param details The SIP information related to this request if the device supports
+ * supplying this information. This parameter will be {@code null} if this
+ * information is not available.
*/
default void onComplete(@Nullable SipDetails details) {
onComplete();
@@ -507,10 +522,16 @@
/**
* The pending request has resulted in an error and may need to be retried, depending on the
* error code.
+ *
+ * This method contains more information about the underlying SIP transaction if it exists.
+ * If this information is not needed, {@link #onError(int, long)} can be implemented
+ * instead.
* @param errorCode The reason for the framework being unable to process the request.
* @param retryIntervalMillis The time in milliseconds the requesting application should
* wait before retrying, if non-zero.
- * @param details The SIP information related to this request.
+ * @param details The SIP information related to this request if the device supports
+ * supplying this information. This parameter will be {@code null} if this
+ * information is not available.
*/
default void onError(@ErrorCode int errorCode, long retryIntervalMillis,
@Nullable SipDetails details) {
diff --git a/telephony/java/android/telephony/ims/aidl/IImsSmsListener.aidl b/telephony/java/android/telephony/ims/aidl/IImsSmsListener.aidl
index 5aa58c1..ae677ca 100644
--- a/telephony/java/android/telephony/ims/aidl/IImsSmsListener.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsSmsListener.aidl
@@ -24,4 +24,5 @@
void onSendSmsResult(int token, int messageRef, int status, int reason, int networkErrorCode);
void onSmsStatusReportReceived(int token, in String format, in byte[] pdu);
void onSmsReceived(int token, in String format, in byte[] pdu);
+ void onMemoryAvailableResult(int token, int status, int networkErrorCode);
}
diff --git a/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java b/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java
index 17cb3b4..e7e0ec2 100644
--- a/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java
@@ -196,6 +196,8 @@
*
* @param token unique token generated in {@link ImsSmsDispatcher#onMemoryAvailable(void)} that
* should be used when triggering callbacks for this specific message.
+ *
+ * @hide
*/
public void onMemoryAvailable(int token) {
// Base Implementation - Should be overridden
@@ -403,6 +405,38 @@
}
/**
+ * This API is used to report the result of sending
+ * RP-SMMA to framework based on received network responses(RP-ACK,
+ * RP-ERROR or SIP error).
+ *
+ * @param token provided in {@link #onMemoryAvailable()}.
+ * @param result based on RP-ACK or RP_ERROR
+ * @param networkErrorCode the error code reported by the carrier
+ * network if sending this SMS has resulted in an error or
+ * {@link #RESULT_NO_NETWORK_ERROR} if no network error was generated. See
+ * 3GPP TS 24.011 Section 7.3.4 for valid error codes and more
+ * information.
+ *
+ * @hide
+ */
+ public final void onMemoryAvailableResult(int token, @SendStatusResult int result,
+ int networkErrorCode) throws RuntimeException {
+ IImsSmsListener listener = null;
+ synchronized (mLock) {
+ listener = mListener;
+ }
+
+ if (listener == null) {
+ throw new RuntimeException("Feature not ready.");
+ }
+ try {
+ listener.onMemoryAvailableResult(token, result, networkErrorCode);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* This method should be triggered by the IMS providers when the status report of the sent
* message is received. The platform will handle the report and notify the IMS provider of the
* result by calling {@link #acknowledgeSmsReport(int, int, int)}.
diff --git a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
index 4fa7f43..3dfc81e 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
@@ -17,6 +17,7 @@
package com.android.internal.telephony;
import android.telephony.ImsiEncryptionInfo;
+import android.net.Uri;
/**
* Interface used to retrieve various phone-related subscriber information.
@@ -220,18 +221,17 @@
String callingPackage, String callingFeatureId);
/**
- * Fetches the EFPSISMSC value from the SIM that contains the Public Service Identity
- * of the SM-SC (either a SIP URI or tel URI), the value is common for both appType
- * {@link #APPTYPE_ISIM} and {@link #APPTYPE_SIM}.
- * The EFPSISMSC value is used by the ME to submit SMS over IP as defined in 24.341 [55].
+ * Fetches the EF_PSISMSC value from the UICC that contains the Public Service Identity of
+ * the SM-SC (either a SIP URI or tel URI). The EF_PSISMSC of ISIM and USIM can be found in
+ * DF_TELECOM.
+ * The EF_PSISMSC value is used by the ME to submit SMS over IP as defined in 24.341 [55].
*
- * @param appType ICC Application type {@link #APPTYPE_ISIM} or {@link #APPTYPE_USIM}
- * @return SIP URI or tel URI of the Public Service Identity of the SM-SC
+ * @return Uri : Public Service Identity of SM-SC
* @throws SecurityException if the caller does not have the required permission/privileges
* @hide
*/
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)")
- String getSmscIdentity(int subId, int appType);
+ Uri getSmscIdentity(int subId, int appType);
/**
* Fetches the sim service table from the EFUST/EFIST based on the application type
@@ -249,9 +249,9 @@
* @param appType of type int of either {@link #APPTYPE_USIM} or {@link #APPTYPE_ISIM}.
* @return HexString represents sim service table else null.
* @throws SecurityException if the caller does not have the required permission/privileges
+ * @throws IllegalStateException in case if phone or UiccApplication is not available.
* @hide
*/
-
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)")
String getSimServiceTable(int subId, int appType);
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/LaunchAppShowImeAndDialogThemeAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/LaunchAppShowImeAndDialogThemeAppTest.kt
index da3c62d..cb530da 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/LaunchAppShowImeAndDialogThemeAppTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/LaunchAppShowImeAndDialogThemeAppTest.kt
@@ -16,7 +16,6 @@
package com.android.server.wm.flicker.ime
-import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
import android.view.WindowInsets.Type.ime
import android.view.WindowInsets.Type.navigationBars
@@ -64,16 +63,6 @@
transitions { testApp.dismissDialog(wmHelper) }
}
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
-
/** Checks that [ComponentNameMatcher.IME] layer becomes visible during the transition */
@Presubmit @Test fun imeWindowIsAlwaysVisible() = flicker.imeWindowIsAlwaysVisible()
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowFromFixedOrientationAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowFromFixedOrientationAppTest.kt
index c2526d3..0e732b5 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowFromFixedOrientationAppTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowFromFixedOrientationAppTest.kt
@@ -16,7 +16,7 @@
package com.android.server.wm.flicker.ime
-import android.platform.test.annotations.Postsubmit
+import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Presubmit
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.BaseTest
@@ -68,25 +68,11 @@
teardown { imeTestApp.exit(wmHelper) }
}
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
-
- @Postsubmit
- @Test
- override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
-
@Presubmit @Test fun imeWindowBecomesVisible() = flicker.imeWindowBecomesVisible()
@Presubmit @Test fun imeLayerBecomesVisible() = flicker.imeLayerBecomesVisible()
- @Postsubmit
+ @FlakyTest(bugId = 240918620)
@Test
fun snapshotStartingWindowLayerCoversExactlyOnApp() {
Assume.assumeFalse(isShellTransitionsEnabled)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTest.kt
index a6bbf54..477ddb3 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTest.kt
@@ -17,7 +17,6 @@
package com.android.server.wm.flicker.ime
import android.platform.test.annotations.FlakyTest
-import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.BaseTest
@@ -92,52 +91,10 @@
wmHelper.StateSyncBuilder().withFullScreenApp(imeTestApp).waitForAndVerify()
}
}
-
/** {@inheritDoc} */
- @Postsubmit
+ @FlakyTest(bugId = 265016201)
@Test
- override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit @Test override fun entireScreenCovered() = super.entireScreenCovered()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarLayerIsVisibleAtStartAndEnd() =
- super.statusBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun statusBarLayerPositionAtStartAndEnd() = super.statusBarLayerPositionAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
- super.visibleLayersShownMoreThanOneConsecutiveEntry()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
- super.visibleWindowsShownMoreThanOneConsecutiveEntry()
+ override fun entireScreenCovered() = super.entireScreenCovered()
@Presubmit
@Test
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenCameraOnDoubleClickPowerButton.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenCameraOnDoubleClickPowerButton.kt
new file mode 100644
index 0000000..41316d8
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenCameraOnDoubleClickPowerButton.kt
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker.launch
+
+import android.platform.test.annotations.Postsubmit
+import android.platform.test.annotations.RequiresDevice
+import android.view.KeyEvent
+import com.android.server.wm.flicker.FlickerBuilder
+import com.android.server.wm.flicker.FlickerTest
+import com.android.server.wm.flicker.FlickerTestFactory
+import com.android.server.wm.flicker.annotation.FlickerServiceCompatible
+import com.android.server.wm.flicker.helpers.CameraAppHelper
+import com.android.server.wm.flicker.helpers.setRotation
+import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.rules.RemoveAllTasksButHomeRule
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test cold launching camera from launcher by double pressing power button
+ *
+ * To run this test: `atest FlickerTests:OpenCameraOnDoubleClickPowerButton`
+ *
+ * Actions:
+ * ```
+ * Make sure no apps are running on the device
+ * Launch an app [testApp] and wait animation to complete
+ * ```
+ * Notes:
+ * ```
+ * 1. Some default assertions (e.g., nav bar, status bar and screen covered)
+ * are inherited [OpenAppTransition]
+ * 2. Part of the test setup occurs automatically via
+ * [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ * including configuring navigation mode, initial orientation and ensuring no
+ * apps are running before setup
+ * ```
+ */
+@RequiresDevice
+@FlickerServiceCompatible
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class OpenCameraOnDoubleClickPowerButton(flicker: FlickerTest) :
+ OpenAppFromLauncherTransition(flicker) {
+ private val cameraApp = CameraAppHelper(instrumentation)
+
+ override val transition: FlickerBuilder.() -> Unit
+ get() = {
+ setup {
+ RemoveAllTasksButHomeRule.removeAllTasksButHome()
+ this.setRotation(flicker.scenario.startRotation)
+ }
+ transitions {
+ device.pressKeyCode(KeyEvent.KEYCODE_POWER)
+ device.pressKeyCode(KeyEvent.KEYCODE_POWER)
+ wmHelper.StateSyncBuilder().withWindowSurfaceAppeared(cameraApp).waitForAndVerify()
+ }
+ teardown { RemoveAllTasksButHomeRule.removeAllTasksButHome() }
+ }
+
+ @Postsubmit @Test override fun appLayerBecomesVisible() = super.appLayerBecomesVisible()
+
+ @Postsubmit @Test override fun appWindowAsTopWindowAtEnd() = super.appWindowAsTopWindowAtEnd()
+
+ @Postsubmit @Test override fun appWindowBecomesTopWindow() = super.appWindowBecomesTopWindow()
+
+ @Postsubmit @Test override fun appWindowBecomesVisible() = super.appWindowBecomesVisible()
+
+ @Postsubmit @Test override fun appLayerReplacesLauncher() = super.appLayerReplacesLauncher()
+
+ @Postsubmit @Test override fun appWindowIsTopWindowAtEnd() = super.appWindowIsTopWindowAtEnd()
+
+ @Postsubmit
+ @Test
+ override fun appWindowReplacesLauncherAsTopWindow() =
+ super.appWindowReplacesLauncherAsTopWindow()
+
+ @Postsubmit @Test override fun focusChanges() = super.focusChanges()
+
+ @Postsubmit @Test override fun entireScreenCovered() = super.entireScreenCovered()
+
+ @Postsubmit
+ @Test
+ override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
+
+ @Postsubmit
+ @Test
+ override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
+
+ @Postsubmit
+ @Test
+ override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
+
+ @Postsubmit
+ @Test
+ override fun statusBarLayerIsVisibleAtStartAndEnd() =
+ super.statusBarLayerIsVisibleAtStartAndEnd()
+
+ @Postsubmit
+ @Test
+ override fun statusBarLayerPositionAtStartAndEnd() = super.statusBarLayerPositionAtStartAndEnd()
+
+ @Postsubmit
+ @Test
+ override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
+
+ @Postsubmit
+ @Test
+ override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
+
+ @Postsubmit
+ @Test
+ override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible()
+
+ @Postsubmit
+ @Test
+ override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
+ super.visibleLayersShownMoreThanOneConsecutiveEntry()
+
+ @Postsubmit
+ @Test
+ override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
+ super.visibleWindowsShownMoreThanOneConsecutiveEntry()
+
+ companion object {
+ /**
+ * Creates the test configurations.
+ *
+ * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
+ * navigation modes.
+ */
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): Collection<FlickerTest> {
+ return FlickerTestFactory.nonRotationTests()
+ }
+ }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTestCfArm.kt
new file mode 100644
index 0000000..e6cdd1e
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTestCfArm.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker.quickswitch
+
+import com.android.server.wm.flicker.FlickerTest
+import com.android.server.wm.flicker.FlickerTestFactory
+import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import com.android.server.wm.traces.common.Rect
+import com.android.server.wm.traces.common.service.PlatformConsts
+import org.junit.FixMethodOrder
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class QuickSwitchBetweenTwoAppsBackTestCfArm(flicker: FlickerTest) :
+ QuickSwitchBetweenTwoAppsBackTest(flicker) {
+ companion object {
+ private var startDisplayBounds = Rect.EMPTY
+
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): Collection<FlickerTest> {
+ return FlickerTestFactory.nonRotationTests(
+ supportedNavigationModes = listOf(PlatformConsts.NavBar.MODE_GESTURAL)
+ )
+ }
+ }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTestCfArm.kt
new file mode 100644
index 0000000..aa9adf0
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTestCfArm.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker.quickswitch
+
+import com.android.server.wm.flicker.FlickerTest
+import com.android.server.wm.flicker.FlickerTestFactory
+import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import com.android.server.wm.traces.common.Rect
+import com.android.server.wm.traces.common.service.PlatformConsts
+import org.junit.FixMethodOrder
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class QuickSwitchBetweenTwoAppsForwardTestCfArm(flicker: FlickerTest) :
+ QuickSwitchBetweenTwoAppsForwardTest(flicker) {
+ companion object {
+ private var startDisplayBounds = Rect.EMPTY
+
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): Collection<FlickerTest> {
+ return FlickerTestFactory.nonRotationTests(
+ supportedNavigationModes = listOf(PlatformConsts.NavBar.MODE_GESTURAL)
+ )
+ }
+ }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt
index df91754..e06a8d6 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt
@@ -53,7 +53,7 @@
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class QuickSwitchFromLauncherTest(flicker: FlickerTest) : BaseTest(flicker) {
+open class QuickSwitchFromLauncherTest(flicker: FlickerTest) : BaseTest(flicker) {
private val testApp = SimpleAppHelper(instrumentation)
/** {@inheritDoc} */
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTestCfArm.kt
new file mode 100644
index 0000000..8b21603
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTestCfArm.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker.quickswitch
+
+import com.android.server.wm.flicker.FlickerTest
+import com.android.server.wm.flicker.FlickerTestFactory
+import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import com.android.server.wm.traces.common.service.PlatformConsts
+import org.junit.FixMethodOrder
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+open class QuickSwitchFromLauncherTestCfArm(flicker: FlickerTest) :
+ QuickSwitchFromLauncherTest(flicker) {
+ companion object {
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): Collection<FlickerTest> {
+ return FlickerTestFactory.nonRotationTests(
+ supportedNavigationModes = listOf(PlatformConsts.NavBar.MODE_GESTURAL),
+ // TODO: Test with 90 rotation
+ supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ )
+ }
+ }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
index 1b23952..8b250c3 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
@@ -16,7 +16,6 @@
package com.android.server.wm.flicker.rotation
-import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.IwTest
import android.platform.test.annotations.Presubmit
import androidx.test.filters.RequiresDevice
@@ -121,11 +120,6 @@
rotationLayerAppearsAndVanishesAssertion()
}
- /** {@inheritDoc} */
- @FlakyTest(bugId = 206753786)
- @Test
- override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
-
@Test
@IwTest(focusArea = "framework")
override fun cujCompleted() {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
index c26485b..d76c94d 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
@@ -16,7 +16,6 @@
package com.android.server.wm.flicker.rotation
-import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.IwTest
import android.platform.test.annotations.Presubmit
import android.view.WindowManager
@@ -201,11 +200,6 @@
flicker.assertEventLog { this.focusDoesNotChange() }
}
- /** {@inheritDoc} */
- @FlakyTest
- @Test
- override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
-
@Test
@IwTest(focusArea = "framework")
override fun cujCompleted() {
@@ -224,6 +218,7 @@
runAndIgnoreAssumptionViolation { appLayerAlwaysVisible() }
runAndIgnoreAssumptionViolation { navBarLayerIsVisibleAtStartAndEnd() }
runAndIgnoreAssumptionViolation { navBarWindowIsAlwaysVisible() }
+ runAndIgnoreAssumptionViolation { navBarLayerPositionAtStartAndEnd() }
runAndIgnoreAssumptionViolation { taskBarLayerIsVisibleAtStartAndEnd() }
runAndIgnoreAssumptionViolation { taskBarWindowIsAlwaysVisible() }
}
diff --git a/tests/Input/src/com/android/test/input/InputDeviceTest.java b/tests/Input/src/com/android/test/input/InputDeviceTest.java
index 797e818..ddcc811 100644
--- a/tests/Input/src/com/android/test/input/InputDeviceTest.java
+++ b/tests/Input/src/com/android/test/input/InputDeviceTest.java
@@ -69,7 +69,7 @@
}
private void assertInputDeviceParcelUnparcel(KeyCharacterMap keyCharacterMap) {
- final InputDevice device = new InputDevice.Builder()
+ final InputDevice.Builder deviceBuilder = new InputDevice.Builder()
.setId(DEVICE_ID)
.setGeneration(42)
.setControllerNumber(43)
@@ -88,8 +88,20 @@
.setHasBattery(true)
.setKeyboardLanguageTag("en-US")
.setKeyboardLayoutType("qwerty")
- .setSupportsUsi(true)
- .build();
+ .setSupportsUsi(true);
+
+ for (int i = 0; i < 30; i++) {
+ deviceBuilder.addMotionRange(
+ MotionEvent.AXIS_GENERIC_1,
+ InputDevice.SOURCE_UNKNOWN,
+ i,
+ i + 1,
+ i + 2,
+ i + 3,
+ i + 4);
+ }
+
+ final InputDevice device = deviceBuilder.build();
Parcel parcel = Parcel.obtain();
device.writeToParcel(parcel, 0);
diff --git a/tests/Input/src/com/android/test/input/MotionPredictorTest.kt b/tests/Input/src/com/android/test/input/MotionPredictorTest.kt
index 46aad9f..bc363b0 100644
--- a/tests/Input/src/com/android/test/input/MotionPredictorTest.kt
+++ b/tests/Input/src/com/android/test/input/MotionPredictorTest.kt
@@ -31,15 +31,14 @@
import androidx.test.filters.SmallTest
import androidx.test.platform.app.InstrumentationRegistry
-import org.mockito.Mockito.mock
-import org.mockito.Mockito.`when`
-
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.`when`
import java.time.Duration
@@ -49,7 +48,6 @@
x: Float,
y: Float,
): MotionEvent{
- // One-time: send a DOWN event
val pointerCount = 1
val properties = arrayOfNulls<MotionEvent.PointerProperties>(pointerCount)
val coords = arrayOfNulls<MotionEvent.PointerCoords>(pointerCount)
diff --git a/tests/Internal/src/com/android/internal/app/OWNERS b/tests/Internal/src/com/android/internal/app/OWNERS
new file mode 100644
index 0000000..d55dc78
--- /dev/null
+++ b/tests/Internal/src/com/android/internal/app/OWNERS
@@ -0,0 +1,2 @@
+# Locale related test
+per-file *Locale* = file:/services/core/java/com/android/server/locales/OWNERS
diff --git a/tests/MotionPrediction/Android.bp b/tests/MotionPrediction/Android.bp
index b9d01da..6cda8f0 100644
--- a/tests/MotionPrediction/Android.bp
+++ b/tests/MotionPrediction/Android.bp
@@ -26,6 +26,5 @@
android_app {
name: "MotionPrediction",
srcs: ["**/*.kt"],
- platform_apis: true,
- certificate: "platform",
+ sdk_version: "current",
}
diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
index ef324e7..6c89e49 100644
--- a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
+++ b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
@@ -1156,12 +1156,12 @@
private PendingIntent makeIntent() {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
- return PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_MUTABLE_UNAUDITED);
+ return PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE);
}
private PendingIntent makeIntent2() {
Intent intent = new Intent(this, StatusBarTest.class);
- return PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_MUTABLE_UNAUDITED);
+ return PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE);
}
diff --git a/tests/VectorDrawableTest/Android.bp b/tests/VectorDrawableTest/Android.bp
index 9da7c5f..099d874 100644
--- a/tests/VectorDrawableTest/Android.bp
+++ b/tests/VectorDrawableTest/Android.bp
@@ -26,5 +26,7 @@
android_test {
name: "VectorDrawableTest",
srcs: ["**/*.java"],
+ // certificate set as platform to allow testing of @hidden APIs
+ certificate: "platform",
platform_apis: true,
}
diff --git a/tests/VectorDrawableTest/AndroidManifest.xml b/tests/VectorDrawableTest/AndroidManifest.xml
index 5334dac..163e438 100644
--- a/tests/VectorDrawableTest/AndroidManifest.xml
+++ b/tests/VectorDrawableTest/AndroidManifest.xml
@@ -158,6 +158,15 @@
<category android:name="com.android.test.dynamic.TEST"/>
</intent-filter>
</activity>
+ <activity android:name="LottieDrawableTest"
+ android:label="Lottie test bed"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="com.android.test.dynamic.TEST" />
+ </intent-filter>
+ </activity>
</application>
</manifest>
diff --git a/tests/VectorDrawableTest/res/raw/lottie.json b/tests/VectorDrawableTest/res/raw/lottie.json
new file mode 100644
index 0000000..fea571c
--- /dev/null
+++ b/tests/VectorDrawableTest/res/raw/lottie.json
@@ -0,0 +1,123 @@
+{
+ "v":"4.6.9",
+ "fr":60,
+ "ip":0,
+ "op":200,
+ "w":800,
+ "h":600,
+ "nm":"Loader 1 JSON",
+ "ddd":0,
+
+
+ "layers":[
+ {
+ "ddd":0,
+ "ind":1,
+ "ty":4,
+ "nm":"Custom Path 1",
+ "ao": 0,
+ "ip": 0,
+ "op": 300,
+ "st": 0,
+ "sr": 1,
+ "bm": 0,
+ "ks": {
+ "o": { "a":0, "k":100 },
+ "r": { "a":1, "k": [
+ { "s": [ 0 ], "e": [ 360], "i": { "x":0.5, "y":0.5 }, "o": { "x":0.5, "y":0.5 }, "t": 0 },
+ { "t": 200 }
+ ] },
+ "p": { "a":0, "k":[ 300, 300, 0 ] },
+ "a": { "a":0, "k":[ 100, 100, 0 ] },
+ "s": { "a":1, "k":[
+ { "s": [ 100, 100 ], "e": [ 200, 200 ], "i": { "x":0.5, "y":0.5 }, "o": { "x":0.5, "y":0.5 }, "t": 0 },
+ { "s": [ 200, 200 ], "e": [ 100, 100 ], "i": { "x":0.5, "y":0.5 }, "o": { "x":0.5, "y":0.5 }, "t": 100 },
+ { "t": 200 }
+ ] }
+ },
+
+ "shapes":[
+ {
+ "ty":"gr",
+ "it":[
+ {
+ "ty" : "sh",
+ "nm" : "Path 1",
+ "ks" : {
+ "a" : 1,
+ "k" : [
+ {
+ "s": [ {
+ "i": [ [ 0, 50 ], [ -50, 0 ], [ 0, -50 ], [ 50, 0 ] ],
+ "o": [ [ 0, -50 ], [ 50, 0 ], [ 0, 50 ], [ -50, 0 ] ],
+ "v": [ [ 0, 100 ], [ 100, 0 ], [ 200, 100 ], [ 100, 200 ] ],
+ "c": true
+ } ],
+ "e": [ {
+ "i": [ [ 50, 50 ], [ -50, 0 ], [ -50, -50 ], [ 50, 50 ] ],
+ "o": [ [ 50, -50 ], [ 50, 0 ], [ -50, 50 ], [ -50, 50 ] ],
+ "v": [ [ 0, 100 ], [ 100, 0 ], [ 200, 100 ], [ 100, 200 ] ],
+ "c": true
+ } ],
+ "i": { "x":0.5, "y":0.5 },
+ "o": { "x":0.5, "y":0.5 },
+ "t": 0
+ },
+ {
+ "s": [ {
+ "i": [ [ 50, 50 ], [ -50, 0 ], [ -50, -50 ], [ 50, 50 ] ],
+ "o": [ [ 50, -50 ], [ 50, 0 ], [ -50, 50 ], [ -50, 50 ] ],
+ "v": [ [ 0, 100 ], [ 100, 0 ], [ 200, 100 ], [ 100, 200 ] ],
+ "c": true
+ } ],
+ "e": [ {
+ "i": [ [ 0, 50 ], [ -50, 0 ], [ 0, -50 ], [ 50, 0 ] ],
+ "o": [ [ 0, -50 ], [ 50, 0 ], [ 0, 50 ], [ -50, 0 ] ],
+ "v": [ [ 0, 100 ], [ 100, 0 ], [ 200, 100 ], [ 100, 200 ] ],
+ "c": true
+ } ],
+ "i": { "x":0.5, "y":0.5 },
+ "o": { "x":0.5, "y":0.5 },
+ "t": 100
+ },
+ {
+ "t": 200
+ }
+ ]
+ }
+ },
+
+ {
+ "ty": "st",
+ "nm": "Stroke 1",
+ "lc": 1,
+ "lj": 1,
+ "ml": 4,
+ "w" : { "a": 1, "k": [
+ { "s": [ 30 ], "e": [ 50 ], "i": { "x":0.5, "y":0.5 }, "o": { "x":0.5, "y":0.5 }, "t": 0 },
+ { "s": [ 50 ], "e": [ 30 ], "i": { "x":0.5, "y":0.5 }, "o": { "x":0.5, "y":0.5 }, "t": 100 },
+ { "t": 200 }
+ ] },
+ "o" : { "a": 0, "k": 100 },
+ "c" : { "a": 1, "k": [
+ { "s": [ 0, 1, 0 ], "e": [ 1, 0, 0 ], "i": { "x":0.5, "y":0.5 }, "o": { "x":0.5, "y":0.5 }, "t": 0 },
+ { "s": [ 1, 0, 0 ], "e": [ 0, 1, 0 ], "i": { "x":0.5, "y":0.5 }, "o": { "x":0.5, "y":0.5 }, "t": 100 },
+ { "t": 200 }
+ ] }
+ },
+
+ {
+ "ty":"tr",
+ "p" : { "a":0, "k":[ 0, 0 ] },
+ "a" : { "a":0, "k":[ 0, 0 ] },
+ "s" : { "a":0, "k":[ 100, 100 ] },
+ "r" : { "a":0, "k": 0 },
+ "o" : { "a":0, "k":100 },
+ "nm": "Transform"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/LottieDrawableTest.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/LottieDrawableTest.java
new file mode 100644
index 0000000..05eae7b
--- /dev/null
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/LottieDrawableTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.dynamic;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.drawable.LottieDrawable;
+import android.os.Bundle;
+import android.view.View;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Scanner;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class LottieDrawableTest extends Activity {
+ private static final String TAG = "LottieDrawableTest";
+ static final int BACKGROUND = 0xFFF44336;
+
+ class LottieDrawableView extends View {
+ private Rect mLottieBounds;
+
+ private LottieDrawable mLottie;
+
+ LottieDrawableView(Context context, InputStream is) {
+ super(context);
+ Scanner s = new Scanner(is).useDelimiter("\\A");
+ String json = s.hasNext() ? s.next() : "";
+ try {
+ mLottie = LottieDrawable.makeLottieDrawable(json);
+ } catch (IOException e) {
+ throw new RuntimeException(TAG + ": error parsing test Lottie");
+ }
+ mLottie.start();
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ canvas.drawColor(BACKGROUND);
+
+ mLottie.setBounds(mLottieBounds);
+ mLottie.draw(canvas);
+ }
+
+ public void setLottieSize(Rect bounds) {
+ mLottieBounds = bounds;
+ }
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ InputStream is = getResources().openRawResource(R.raw.lottie);
+
+ LottieDrawableView view = new LottieDrawableView(this, is);
+ view.setLottieSize(new Rect(0, 0, 900, 900));
+ setContentView(view);
+ }
+}
diff --git a/tools/lint/common/src/main/java/com/google/android/lint/Constants.kt b/tools/lint/common/src/main/java/com/google/android/lint/Constants.kt
index 3d5d01c..0ef165f 100644
--- a/tools/lint/common/src/main/java/com/google/android/lint/Constants.kt
+++ b/tools/lint/common/src/main/java/com/google/android/lint/Constants.kt
@@ -35,6 +35,6 @@
Method(CLASS_ACTIVITY_MANAGER_INTERNAL, "enforceCallingPermission")
)
-const val ANNOTATION_PERMISSION_METHOD = "android.content.pm.PermissionMethod"
-const val ANNOTATION_PERMISSION_NAME = "android.content.pm.PermissionName"
+const val ANNOTATION_PERMISSION_METHOD = "android.annotation.PermissionMethod"
+const val ANNOTATION_PERMISSION_NAME = "android.annotation.PermissionName"
const val ANNOTATION_PERMISSION_RESULT = "android.content.pm.PackageManager.PermissionResult"
diff --git a/tools/processors/immutability/Android.bp b/tools/processors/immutability/Android.bp
index 2ce785f..a7d69039 100644
--- a/tools/processors/immutability/Android.bp
+++ b/tools/processors/immutability/Android.bp
@@ -60,6 +60,9 @@
java_resources: [":ImmutabilityAnnotationJavaSource"],
test_suites: ["general-tests"],
+ test_options: {
+ unit_test: true,
+ },
javacflags: [
"--add-modules=jdk.compiler",
"--add-exports jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED",